home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 078 (1990-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 078 (1990-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / TrackSalve / TrackSalve / Source / patch.a < prev    next >
Text File  |  1990-06-17  |  84KB  |  2,505 lines

  1. *  Patch.a  -    Copyright 1990 D.W.Reisig
  2. *
  3. *   #     date     by    Comment
  4. *  -- --------- ----- ---------------------
  5. *   0 29-Oct-89     DWR   Created for Tracksalve
  6. *   1 10-Apr-90  DWR   TrackSalve 1.3, Complete overhaul
  7. *
  8.  
  9. *        nolist
  10.         ifnd    IFILES
  11. IFILES        set    1
  12.         INCLUDE "Call.i"
  13.         INCLUDE "globdefs.i"
  14.         INCLUDE "ts.i"
  15.         INCLUDE "exec/tasks.i"
  16.         INCLUDE "hardware/custom.i"
  17.         INCLUDE    "hardware/dmabits.i"
  18.         include "graphics/text.i"
  19.         include "graphics/rastport.i"
  20. *        include "intuition/intuitionbase.i"
  21. *        include "intuition/intuition.i"
  22. *        include "intuition/screens.i"
  23.         include "devices/inputevent.i"
  24.  
  25.         ifnd    INTUITION_INTUITION_I
  26. GADGETUP    equ    $00000040
  27. RAWKEY        equ    $00000400
  28. WINDOWDEPTH    equ    $0004
  29. WINDOWDRAG    equ    $0002
  30. SIMPLE_REFRESH    equ    $0040
  31. NOCAREREFRESH    equ    $00020000
  32. ACTIVATE    equ    $1000
  33. GADGHCOMP    equ    $0000
  34. GADGHBOX    equ    $0001
  35. GADGIMAGE    equ    $0004
  36. GADGHIMAGE    equ    $0002
  37. BOOLGADGET    equ    $0001
  38. REQGADGET    equ    $1000
  39. RELVERIFY    equ    $0001
  40. ENDGADGET    equ    $0004
  41. wd_LeftEdge    equ    4
  42. wd_UserPort    equ    86
  43. im_Class    equ    20
  44. im_Code        equ    24
  45. im_IAddress    equ    28
  46.         endc
  47.  
  48.         ifnd    INTUITION_SCREENS_I
  49. WBENCHSCREEN    equ    $0001
  50. sc_DetailPen    equ    $14a
  51.         endc
  52.  
  53.         ifnd    INTUITION_INTUITIONBASE_I
  54. ib_FirstScreen    equ    $3c
  55.         endc
  56.  
  57.         endc
  58.  
  59. *        list
  60.  
  61.  
  62. *********************************************************
  63. *
  64. *  TSCodeBegin
  65. *
  66. *  Begin of code that extents/replaces Trackdisk code.
  67. *  For (relocation) references inside this section, this must stay the first location of this
  68. *  section.  So do not put any code before TSCodeBegin.
  69. *  TSCodeBegin is made globally known because some routine must copy us from here to an
  70. *  allocated space.  Because all references to the locationcounter until TSCodeEnd are done
  71. *  from within this part or from patched Trackdisk code, none of these locations should be made
  72. *  external available.
  73. *
  74.  
  75.         SECTION text,code
  76.  
  77.         Func    TSCodeBegin,_TSCodeBegin
  78.  
  79.         
  80.  
  81.  
  82. *********************************************************
  83. *
  84. *  We jump to these addresses when changing from ROM to TS.  Special inits must be done here.
  85. *
  86. *  Upon entry:    a3    TDU_
  87. *        a6    SysBase
  88. *        (a7)    TDD_
  89.  
  90. *--    First TrackSalve pc if trackdisk is in the taskloop's single subroutine
  91.  
  92. FirstPCSub    move.l    #$300,d0            %
  93.         move.l    a6,-(a7)            %
  94.         move.l    TDD_SysBase(a6),a6        %
  95.         LibCall    Wait                %
  96.  
  97. *--    First TrackSalve pc if Trackdisk is in its taskloop Wait call
  98.  
  99. FirstPCWait    move.b    #F_RAM,UNIT_pad(a3)        Set flags to executing in RAM and clear all other
  100.         move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  101.         move.l    a3,UD_BlitNode+TSBN_Unit(a2)    Install Unit pointer in blitnode
  102.         
  103.         ;bra.s    TDE_TaskLoop            Continue normal loop
  104.  
  105.  
  106. *********************************************************
  107. *
  108. *  Extension of Trackdisks main task loop.
  109. *  We are free to use a2, but its value may have been changed upon entry.
  110. *  A6 contains SysBase and the device pointer must be restored by a pull from the stack.
  111. *  For IO with fast memory buffers we use the fastest possible copy routine.  Our
  112. *  routine is faster than the Exec CopyMem(), unless it is replaced.  Adapt to it.
  113. *  Then we check wether we initiated a terminal state.  If so, we do not check external
  114. *  commands anymore, but continue to finish the special functions and return to ROM-code
  115. *  in the end.  Otherwise we compare the external commands with the already active
  116. *  functions and if they differ, we see that they are initiated/terminated.
  117. *
  118. *  Upon entry:    a3    TDU_
  119. *        a6    SysBase
  120. *        (a7)    TDD_
  121. *
  122. *  Usage:    a2    UD_
  123. *
  124.  
  125. TDE_TaskLoop    ;Inserted by a bra at the end of the taskloop
  126.  
  127. TL_        move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  128.  
  129. *--    Find the most efficent copy routine
  130.  
  131.         lea.l    CopySectCPU(pc),a0        Asume our dedicated routine to be the best
  132.         move.l    _LVOCopyMem+2(a6),d0        Adress of exec CopyMem function
  133.         sub.l    LN_NAME(a6),d0            Find distance of some address near the begin of Exec
  134.         swap.w    d0                Divide by 65k
  135.         tst.w    d0                Distance less than 65k?
  136.         beq.s    10$                Yes, CopyMem function not replaced
  137.         lea.l    CopySectExec(pc),a0        No, replaced, use replaced CopyMem function
  138. 10$        move.l    a0,UD_CopySect(a2)        Store function to use for copy sectors
  139.  
  140.         move.l    (a7)+,a6            % Perform replaced instruction. Restore device pointer
  141.  
  142. *--    Check change in TrackSalve functions
  143.  
  144.         btst    #B_TERM,UNIT_pad(a3)        Change of control?
  145.         bne.s    TL_TermTS            Yes..
  146.         move.b    UD_Cmd1(a2),d0            Command from outside
  147.         cmp.b    UNIT_pad(a3),d0            Same as presently active?
  148.         beq    TD_TaskLoop            AE64 Yes, continue task..
  149.  
  150.         btst    #B_TERM,d0            Change of control?
  151.         bne    TL_TermTS            Yes..
  152.         bsr    ChkChgReadOnly            Check change of write protection
  153.         move.b    UD_Cmd1(a2),d0            Get commands
  154.         bsr    ChkChgSalve            Check change of readerror handling
  155.         move.b    UD_Cmd1(a2),d0            Get commands
  156.         bsr    ChkChgNoClick            Check change of diskchange detection
  157.         move.b    UD_Cmd1(a2),d0            Get commands
  158.         bsr    ChkChgVerify            Check change of verify function
  159.         move.b    UD_Cmd1(a2),d0            Get commands
  160.         bsr    ChkChgUpdate            Check change of auto update function
  161.  
  162.         bra    TD_TaskLoop            AE64 Continue task..
  163.  
  164. *--    Initiate or continue terminal state.  Stay in the taskloop until all functions are switched off.
  165.  
  166. TL_TermTS    bset.b    #B_TERM,UNIT_pad(a3)        Set status of TS to terminating
  167.         moveq.l #0,d0                Readonly off
  168.         bsr    ChkChgReadOnly            Check change of write protection
  169.         moveq.l #0,d0                Salve off
  170.         bsr    ChkChgSalve            Check change of readerror handling
  171.         moveq.l #0,d0                NoClick off
  172.         bsr    ChkChgNoClick            Check change of diskchange detection
  173.         moveq.l #0,d0                Verify off
  174.         bsr    ChkChgVerify            Check change of verify function
  175.         moveq.l #0,d0                Auto update off
  176.         bsr    ChkChgUpdate            Check change of auto update function
  177.         move.b    UNIT_pad(a3),d0            Current active functions
  178.         and.b    #FUNCTIONS-F_RAM,d0        All extra functions terminated?
  179.         bne    TD_TaskLoop            AE64 No, continue task..
  180.  
  181. *--    We realy stop here.  The taskloop hereafter continues in ROM-code.  Remove any incompatibilities.
  182.  
  183.         move.l    TDU_UnitBuf(a3),a0        The only track buffer possible
  184.         tst.w    TB_TrkNo(a0)            Error in track?
  185.         bmi.s    10$                Yes, don't care about it contents format..
  186.         bsr    MFMTrack            No, ensure proper MFM-format
  187. 10$
  188.         move.l    a6,-(a7)            Preserve a6 AND undo the already executed "move.l (a7)+,a6"
  189.         move.l    TDD_SysBase(a6),a6        Trackdisk's SysBase
  190.         move.l    UD_ReturnTD(a2),-(a7)        Push ROM-address. With a "rts" we are back in ROM
  191.         movem.l a4/a5,-(a7)
  192.         LibCall Forbid                We do daring things here, like freeing code we are executing!
  193.         move.l    UD_TSControl(a2),a5        Lea the Control structure
  194.         move.l    TSC_TSHook(a5),a4        Lea anchor of all our knowledge
  195.         move.l    a4,a0
  196.         LibCall ObtainSemaphore            We want to be blocked here until others are ready with TSC
  197.  
  198.         moveq.l #0,d0
  199.         move.b    TDU_UnitNr(a3),d0        Trackdisk unit number
  200.         bclr.b    d0,TSC_InUse(a5)        Tell global structure we stopped using it.
  201.         lsl.l    #2,d0                Scale to pointer-index
  202.         clr.l    TSC_UnitData(a5,d0.l)        Clear UnitData pointer in TSC structure
  203.         move.l    UD_Userdata(a2),TDU_TCB+TC_Userdata(a3) Restore original value in Task control block
  204.         move.b    #0,UNIT_pad(a3)            Back to what it was perhaps
  205.         lea.l    UD_TDReq(a2),a1            Trackdisk IORequest
  206.         cmp.l    IO_UNIT(a1),a3            Our request? (of course it is)
  207.         bne.s    20$                No, skip close..
  208.         LibCall CloseDevice
  209. 20$
  210.  
  211. *--    Return memory of the TSControl structure if there are no other users of it anymore.
  212.  
  213.         tst.b    TSC_InUse(a5)            Any users left?
  214.         bne.s    40$                Yes, do not free it..
  215.         move.l    TSC_Buffer(a5),d1        The install program allocates this buffer.  Its presence may
  216.                                 ; not yet have been processed
  217.         beq.s    30$                No buffer..
  218.         move.l    d1,a1                Buffer
  219.         move.l    #SB_SIZE,d0            Its size
  220.         LibCall FreeMem                Back to the system
  221. 30$        move.l    TSC_IntuBase(a5),a1        Close Intuition
  222.         LibCall CloseLibrary
  223.         move.l    a5,a1                TSControl structure
  224.         move.l    TSC_Size(a5),d0            Its size (about 10k)
  225.         LibCall FreeMem                Free it
  226.         clr.l    TSH_TSControl(a4)        No TSControl structure anymore in TSHook
  227. 40$
  228.  
  229. *--    Maybe the TSControl structure does not exist anymore.  We cannot return from Permit() here, so we jump to it.
  230. *    The return address is already on the stack and points to the correct position in ROM-code.
  231.  
  232.         move.l    a4,a0                Lea TSHook structure
  233.         LibCall ReleaseSemaphore        We are (almost) ready with the TSControl structure
  234.         movem.l (a7)+,a4/a5
  235.         xref    _LVOPermit
  236.         jmp    _LVOPermit(a6)            Taskswitching on and back to ROM
  237.  
  238.  
  239. *-------------------------------------------------------*
  240. *
  241. *  ChkChgSalve
  242. *
  243. *  This routine handles the switch from salve function on and off. If there are no other
  244. *  users of this function left, release the large chip-buffer (about 25k).  If the function
  245. *  is switched on, check the presence of the buffer.  If not there, allocate it.
  246. *
  247. *  Input:    d0    UD_Cmd1
  248. *        a2    UD_
  249. *        a3    TDU_
  250. *        a6    TDD_
  251. *
  252.  
  253.  
  254. ChkChgSalve
  255. CS_        move.b    UNIT_pad(a3),d1            Presently active functions
  256.         and.b    #F_SALVE,d0            Select salve-bit in command
  257.         and.b    #F_SALVE,d1            Select salve-bit in active functions
  258.         cmp.b    d0,d1                Salve-action changed?
  259.         bne.s    CS_ChangeSalve            Yes, see that it is done..
  260.         rts
  261.  
  262. *--    We must protect the allocation, freeing and administration of the salve buffer with the TSC semaphore.
  263.  
  264. CS_ChangeSalve    movem.l d2/d3/a5/a6,-(a7)
  265.         move.l    d0,d2                Keep salve command
  266.         move.b    TDU_UnitNr(a3),d3        Unit number
  267.         move.l    UD_TSControl(a2),a5        TSControl structure
  268.         move.l    TDD_SysBase(a6),a6        SysBase for Semaphore calls
  269.         move.l    TSC_TSHook(a5),a0        Lea semaphore
  270.         LibCall ObtainSemaphore            We want to be blocked here until others are ready with TSC
  271.         btst    #B_SALVE,d2            Salve requested?
  272.         beq.s    CS_SalveOff            No..
  273.  
  274. CS_SalveOn    bsr    CheckBufAvail            Check presence and allocate if necessary
  275.         beq.s    CS_Rtn                No success..
  276.         bset.b    #B_SALVE,UNIT_pad(a3)        Set function active
  277.         bset.b    d3,TSC_Salve(a5)        Tell global structure that we use the buffer
  278.         bra.s    CS_Rtn                Done..
  279.  
  280. CS_SalveOff    move.l    TDU_UnitBuf(a3),a0        Lea trackbuffer.  Salve off; normal error handling
  281.         cmp.b    #SPT,TB_FirstSec(a0)        Error?
  282.         bcs.s    10$                No..
  283.         move.w    #-1,TB_TrkNo(a0)        Yes, invalidate tracknumber
  284. 10$        bclr.b    #B_SALVE,UNIT_pad(a3)        Set function off
  285.         bclr.b    d3,TSC_Salve(a5)        We do not use the buffer into global structure
  286.         bsr    CheckBufFree            Deallocate if we were the last users
  287.  
  288. CS_Rtn        move.l    TSC_TSHook(a5),a0        Lea semaphore
  289.         LibCall ReleaseSemaphore        We are ready with the TSControl structure
  290.         movem.l (a7)+,d2/d3/a5/a6
  291.         rts
  292.  
  293. *-------------------------------------------------------*
  294. *
  295. *  ChkChgVerify
  296. *
  297. *  Handle the switch from verify function on and off.  If there are no other users of this
  298. *  function left, release the large chip-buffer.  If the function is switched on, check the
  299. *  presence of the buffer.  If not there, allocate it.
  300. *
  301. *  Input:    d0    UD_Cmd1
  302. *        a2    UD_
  303. *        a3    TDU_
  304. *        a6    TDD_
  305. *
  306.  
  307. ChkChgVerify
  308. CV_        move.b    UNIT_pad(a3),d1            Presently active functions
  309.         and.b    #(F_VERIFY1+F_VERIFY0),d0    Select Verify-bits in command
  310.         and.b    #(F_VERIFY1+F_VERIFY0),d1    Select Verify-bits in active functions
  311.         cmp.b    d0,d1                Verify-action changed?
  312.         bne.s    CV_ChangeVerify            Yes, see that it is done..
  313.         rts
  314.  
  315. *--    We must protect the allocation, freeing and administration of the salve buffer with the TSC semaphore.
  316.  
  317. CV_ChangeVerify    movem.l d2/d3/a5/a6,-(a7)
  318.         move.l    d0,d2                Keep Verify command
  319.         move.b    TDU_UnitNr(a3),d3        Unit number
  320.         move.l    UD_TSControl(a2),a5        TSControl structure
  321.         move.l    TDD_SysBase(a6),a6        SysBase for Semaphore calls
  322.         move.l    TSC_TSHook(a5),a0        Lea semaphore
  323.         LibCall ObtainSemaphore            We want to be blocked here until others are ready with TSC
  324.         tst.b    d2                Verify requested?
  325.         beq.s    CV_VerifyOff            No..
  326.  
  327. CV_VerifyOn    bsr    CheckBufAvail            Check presence and allocate if necessary
  328.         beq.s    CV_Rtn                No success..
  329.         bset.b    d3,TSC_Verify(a5)        Tell global structure that we use the buffer
  330.         and.b    #~(F_VERIFY1+F_VERIFY0),UNIT_pad(a3) Clear present verify bits
  331.         or.b    d2,UNIT_pad(a3)            Set function active with desired bits
  332.         bra.s    CV_Rtn                Done..
  333.  
  334. CV_VerifyOff    and.b    #~(F_VERIFY1+F_VERIFY0),UNIT_pad(a3) Set function off
  335.         bclr.b    d3,TSC_Verify(a5)        We do not use the buffer into global structure
  336.         bsr    CheckBufFree            Deallocate if we were the last users
  337.         
  338. CV_Rtn        move.l    TSC_TSHook(a5),a0        Lea semaphore
  339.         LibCall ReleaseSemaphore        We are ready with the TSControl structure
  340.         movem.l (a7)+,d2/d3/a5/a6
  341.         rts
  342.  
  343. *-------------------------------------------------------*
  344. *
  345. *  Local subroutine of ChkChgSalve and ChkChgVerify, allocate and free the large chip buffer
  346. *
  347. *  Input:    a5    TSC_
  348.  
  349. CheckBufAvail    tst.l    TSC_Buffer(a5)            Is a buffer present?
  350.         bne.s    10$                Yes, skip allocation
  351.         move.l    #SB_SIZE,d0            No, its size
  352.         move.l    #MEMF_CHIP,d1            And type
  353.         LibCall AllocMem            Ask system about 25k chip
  354.         move.l    d0,TSC_Buffer(a5)        Into global structure. This buffer is shared
  355. 10$        rts
  356.  
  357.  
  358. CheckBufFree    tst.b    TSC_Salve(a5)            Any users left?
  359.         bne.s    10$                Yes, done..
  360.         tst.b    TSC_Verify(a5)            Any users left?
  361.         bne.s    10$                Yes, done..
  362.         move.l    TSC_Buffer(a5),d1        Get buffer
  363.         beq.s    10$                No buffer..
  364.         move.l    d1,a1                Buffer
  365.         move.l    #SB_SIZE,d0            Its size
  366.         LibCall FreeMem                Back to system
  367.         clr.l    TSC_Buffer(a5)            No buffer anymore
  368. 10$        rts
  369.  
  370.  
  371. *-------------------------------------------------------*
  372. *
  373. *  ChkChgNoClick
  374. *
  375. *  Handle the switch from the NoClick function on and off.
  376. *
  377. *  Input:    d0    UD_Cmd1
  378. *        a2    UD_
  379. *        a3    TDU_
  380. *        a6    TDD_
  381. *
  382.  
  383. ChkChgNoClick    btst    #B_NOCLICK,d0            Function to be activated?
  384.         beq.s    10$                No..
  385.         bset.b    #B_NOCLICK,UNIT_pad(a3)        Yes function on
  386.         rts
  387. 10$        bclr.b    #B_NOCLICK,UNIT_pad(a3)        No function off
  388.         rts
  389.  
  390. *-------------------------------------------------------*
  391. *
  392. *  ChkChgUpdate
  393. *
  394. *  Handle the switch from the auto update function on and off.
  395. *
  396. *  Input:    d0    UD_Cmd1
  397. *        a2    UD_
  398. *        a3    TDU_
  399. *        a6    TDD_
  400. *
  401.  
  402. ChkChgUpdate    btst    #B_UPDATE,d0            Function to be activated?
  403.         beq.s    10$                No..
  404.         bset.b    #B_UPDATE,UNIT_pad(a3)        Switch function on, was aready done?
  405.         beq    SetUpdCnt            No, init counter according to present state
  406.         rts
  407. 10$        bclr.b    #B_UPDATE,UNIT_pad(a3)        Set function off
  408.         rts
  409.  
  410. *-------------------------------------------------------*
  411. *
  412. *  ChkChgReadOnly
  413. *
  414. *  Switching ReadOnly on and off must be done a little careful.     Although we have nothing to
  415. *  do with DOS, (and we do not want too, do we?) it would be inconvenient to switch to
  416. *  readonly when DOS is writing.  There is no way to be sure, but an indication might be the
  417. *  state of the motor.    It is the user who initiates the switch.  He must do it at a quiet
  418. *  moment.  Tell him in the manual!  Again we cannot tell DOS directly that we changed the
  419. *  write protection of the disk, but we simulate a disk-change and a shift of the disk
  420. *  protect tab.  We can skip this if the drive is empty or if the present disk is already
  421. *  write protected by its tab.
  422. *
  423. *  Input:    d0    UD_Cmd1
  424. *        a2    UD_
  425. *        a3    TDU_
  426. *        a6    TDD_
  427. *
  428.  
  429. ChkChgReadOnly
  430. RO_        btst    #B_READONLY,d0            Is this drive to be protected?
  431.         beq.s    RO_Off                No, check reverse action..
  432.         btst.b    #B_READONLY,UNIT_pad(a3)    Check real bit
  433.         beq.s    RO_CheckChange            We have to change from r/w to ro..
  434.         rts
  435.  
  436. RO_Off        btst.b    #B_READONLY,UNIT_pad(a3)    Check active function bit
  437.         bne.s    RO_CheckChange            Was set to write-protect, try change to R/W..
  438.         rts
  439.  
  440. RO_CheckChange    btst.b    #1,TDU_Flags(a3)        Is there a disk in the drive?
  441.         bne.s    RO_ChangeROSec            No, just flip RO-bit..
  442.         btst.b    #4,TDU_Flags(a3)        Is there a protected disk in the drive?
  443.         bne.s    RO_ChangeROSec            Yes, just flip RO-bit..
  444.         btst.b    #CIAB_DSKMOTOR,TDU_CiabPb(a3)    Motor off? (We TRY to avoid change during disk (write) access)
  445.         beq.s    RO_Rtn                No, try again later..
  446. RO_ChangeRO    bchg.b    #B_READONLY,UNIT_pad(a3)    Change real bit. This will be checked before the hardware
  447. *        pea.l    RO_Rtn(pc)            Push return address, now we are inside a subroutine
  448.         movem.l d2/a2,-(a7)            Imitate the disk-presence-check inits
  449.         lea.l    _ciab+ciaprb,a2            CIAB-PRB
  450.         bra    TD_NoDisk            99C2 Continue subroutine handling disk absence..
  451.  
  452. RO_ChangeROSec    bchg.b    #B_READONLY,UNIT_pad(a3)    Change function bit. This is checked before the hardware is
  453. RO_Rtn        rts
  454.  
  455.  
  456. *********************************************************
  457. *
  458. *  MFMTrack
  459. *  
  460. *  This routine is to be called just before a write to disk.
  461. *  Set or clear all non-data bits as required to meet the MFM standard except those
  462. *  of the syncwords.  As source we need a buffer in which all databits are valid.
  463. *
  464. *  Input:    a3    TDU_
  465. *        a6    TDD_
  466. *
  467.  
  468. MFMTrack
  469. MT_        move.l    TDU_TCB+TC_Userdata(a3),a1    Lea UnitData structure
  470.         lea.l    UD_BlitNode(a1),a1
  471.  
  472.         move.l    TDU_DiskBuf(a3),a0        Buffer to be MFM updated
  473.         lea.l    TB_Data(a0),a0            
  474.         move.l    a0,TSBN_P0(a1)            Begin of block
  475.         add.w    #SPT*SE_SIZE-2,a0        Add block size to get address of last word
  476.         move.l    a0,TSBN_P1(a1)            Into control structure
  477.         lea.l    BF_MT10(pc),a0
  478.         move.l    a0,bn_function(a1)        First blitter function
  479.         move.l    a6,-(a7)
  480.         move.l    TDD_GfxBase(a6),a6        The graphics library coordinates blitter usage
  481.         LibCall QBlit                Control is returned immedately so we must wait here
  482.         move.l    (a7)+,a6
  483.         bsr    TD_WaitTDPort            A70A Wait for a message we sent to ourself from within Gfx
  484.  
  485. *--    The syncs are gone.  Restore them.
  486.  
  487.         move.l    TDU_DiskBuf(a3),a0
  488.         lea.l    TB_Data+SE_Sync(a0),a0        Lea first sync
  489.         move.l    #SYNCSYNC,d1            The sync pattern
  490.         moveq.l #SPT-1,d0            Number of syncs to restore
  491. MT_PutSync    move.l    d1,(a0)                Restore sync
  492.         add.w    #SE_SIZE,a0            Ea of next sync
  493.         dbra    d0,MT_PutSync            Loop..
  494.  
  495.         rts
  496.  
  497. *********************************************************
  498. *
  499. *  TDE_FormInit,  TDE_CMD_RW
  500. *
  501. *  Find out what kind of buffers are used for IO.
  502. *
  503. *  Input:    a3    TDU_
  504. *
  505. *  Return:    d6.b    Chip
  506. *
  507.  
  508.  
  509. TDE_FormInit    move.l    $28(a4),a5            % Was changed into call to this routine
  510.         move.l    a5,a1                Just loaded IO_DATA in a5, IO buffer
  511.         bra    TestMem                Set memorytype flag d6
  512.  
  513.  
  514.  
  515. *********************************************************
  516. *
  517. *  EncodeSector  EncodeLabel
  518. *
  519. *  Routines to replace the original TD encoding routines.  Because we will validate all
  520. *  non-data bits just before it is written to disk, the encoding just exists of putting
  521. *  the databits into its place in the buffer.  We do so by copiing the data to the
  522. *  upper half of its buffer space, followed by a copy from this upperhalf to the lower half,
  523. *  but*  this time shifted right one bit.  The first copy (512 bytes/128 longs) is done by
  524. *  the blitter if the source is chip, else by some function if non-chip.  The second move
  525. *  and shift is done by the blitter.
  526. *  The encoding of the label is entirely done by the cpu, QBlit has too much overhead
  527. *  to encode 16 bytes.
  528. *
  529. *
  530. *  Input:    a0    Source        Users IO buffer
  531. *        a1    Destination   Sector location in trackdisk's trackbuffer
  532. *        a3    TDU_
  533. *        a6    TDD_
  534. *
  535.  
  536.         
  537. TDR_EncodeLabel    ;Replacing TD-subroutine
  538.         
  539.         move.l    a2,-(a7)
  540.         moveq.l    #TD_LABELSIZE/4-1,d1        Init loop counter
  541.         lea.l    TD_LABELSIZE(a1),a2        Pointer to upper half of labelspace
  542. 10$        move.l    (a0)+,d0            Uncoded value
  543.         move.l    d0,(a2)+            Store unshifted in upper space
  544.         lsr.l    #1,d0                Shift right one bit
  545.         move.l    d0,(a1)+            Store shifted in lower space
  546.         dbra    d1,10$                Loop..
  547.         move.l    (a7)+,a2
  548.         rts
  549.  
  550.         
  551. TDR_EncodeSect    ;Replacing TD-subroutine
  552.  
  553. ES_        movem.l    a2/a5,-(a7)
  554.         move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  555.         lea.l    UD_BlitNode(a2),a5        Lea extended blitnode
  556.  
  557. *--    Second move: source is upperhalf of sector space, destination is lowerhalf and shifted one bit right
  558.  
  559.         move.l    a1,TSBN_P3(a5)            Lowerhalf is destination
  560.         add.w    #TD_SECTOR,a1            Set pointer to upperhalf
  561.         move.l    a1,TSBN_P2(a5)            Upperhalf is  source
  562.  
  563. *--    First move: Depending on the type of source, we use the blitter or some copy routine to copy into upperhalf
  564.  
  565.         tst.b    d6                What kind of memory is the source?
  566.         bne.s    10$                It is chip, we use the blitter for copy..
  567.  
  568. *--    We use the best non-blitter copy routine
  569.  
  570.         move.l    UD_CopySect(a2),a2        Get copy function
  571.         jsr    (a2)                Copy first the source to upper half of destination
  572.         lea.l    BF_ES20(pc),a0            Shift & copy function
  573.         bra.s    20$
  574.  
  575. *--    We use the blitter for copy
  576.  
  577. 10$        move.l    a0,TSBN_P0(a5)            Source
  578.         move.l    a1,TSBN_P1(a5)            Upper half is destination
  579.         lea.l    BF_ES10(pc),a0            Copy and shift & copy function
  580.  
  581. 20$        move.l    a0,bn_function(a5)        First blitter function
  582.         move.l    a5,a1                Pointer to our blitnode
  583.         move.l    a6,-(a7)
  584.         move.l    TDD_GfxBase(a6),a6        The graphics library coordinates blitter usage
  585.         LibCall QBlit                Control is returned immedately so we must wait here
  586.         move.l    (a7)+,a6
  587.         bsr    TD_WaitTDPort            A70A Wait for a message we sent to ourself from within Gfx
  588.         movem.l    (a7)+,a2/a5
  589.         rts
  590.  
  591.  
  592. *-------------------------------------------------------*
  593. *
  594. *  DecodeLabel  DecodeSect
  595. *
  596. *  These routines replace the TD decode routine just for one reason, the allowence of
  597. *  fast memory as I/O buffers.  Again the label is completely decoded by the CPU for
  598. *  the size of the operation.  The sector is decoded by the blitter into the upper
  599. *  halve of the source.  This does no harm because it is MFM'd again before any writes
  600. *  to disk.  From the upper half it is then copied to the destination buffer.
  601. *
  602. *  Input:    a0    Destination  Users IO buffer
  603. *        a1    Source       Sector location in trackdisk's trackbuffer
  604. *        a3    TDU_
  605. *        a6    TDD_
  606. *
  607.  
  608. TDR_DecodeLabel    ;Replacing TD-subroutine
  609.  
  610.         movem.l    d2/d3,-(a7)
  611.         move.l    #$55555555,d2            Data mask
  612.         moveq.l    #TD_LABELSIZE/4-1,d3
  613. 10$        move.l    TD_LABELSIZE(a1),d1        Unshifted data
  614.         and.l    d2,d1                Mask timing bits away
  615.         move.l    (a1)+,d0            Shifted data
  616.         and.l    d2,d0                Mask timing bits away
  617.         lsl.l    #1,d0                Shift back
  618.         or.l    d1,d0                Fold together
  619.         move.l    d0,(a0)+            Store into destination
  620.         dbra    d3,10$                Loop..
  621.         movem.l    (a7)+,d2/d3
  622.         rts
  623.  
  624. TDR_DecodeSect    ;Replacing TD-subroutine
  625.  
  626. DS_        movem.l    d2-d3/a2/a5,-(a7)
  627.         move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  628.         lea.l    UD_BlitNode(a2),a5        Lea extended blitnode
  629.  
  630.         tst.b    d6                Destination chip memory?
  631.         bne.s    10$                Yes..
  632.  
  633. *-    Non-chip destination
  634.  
  635.         add.w    #TD_SECTOR,a1            The sector is decoded into the upper half of the sector location
  636.         move.l    a1,d2                Source of copy to IO buffer is begin of upper half
  637.         move.l    a0,d3                Destination of second copy is IO buffer
  638.         subq.l    #2,a1                Find end of lower half
  639.         move.l    a1,TSBN_P0(a5)            Is pointer for blitter
  640.         add.w    #TD_SECTOR,a1            Find end of upper half
  641.         move.l    a1,TSBN_P1(a5)            Ponter for blitter
  642.         move.l    a1,TSBN_P2(a5)            We decode into the upperhalf
  643.         bra.s    20$
  644.  
  645. *--    Chip destination, blitter in descendinig mode: end of buffers
  646.  
  647. 10$        add.w    #TD_SECTOR-2,a1            Find end of lower half
  648.         move.l    a1,TSBN_P0(a5)            Source pointer for blitter
  649.         add.w    #TD_SECTOR,a1            Find end of upper half
  650.         move.l    a1,TSBN_P1(a5)            Source pointer for blitter
  651.         add.w    #TD_SECTOR-2,a0            Find end of IO buffer
  652.         move.l    a0,TSBN_P2(a5)            Destination pointer for blitter, decode into IO buffer
  653.  
  654. 20$        lea.l    BF_DS10(pc),a0            Blitter decode function
  655.         move.l    a0,bn_function(a5)        Function into blitnode
  656.         move.l    a5,a1                Pointer to our blitnode
  657.         move.l    a6,-(a7)
  658.         move.l    TDD_GfxBase(a6),a6        The graphics library coordinates blitter usage
  659.         LibCall QBlit                Control is returned immedately so we must wait here
  660.         move.l    (a7)+,a6
  661.         bsr    TD_WaitTDPort            A70A Wait for a message we sent to ourself from within Gfx
  662.  
  663.         tst.b    d6                Chip destination?
  664.         bne.s    30$                Yes, data already in the IO buffer..
  665.  
  666. *--    Destination is non chip, use other data copy function
  667.         
  668.         move.l    d2,a0                No, data is in upperhalf of sector location
  669.         move.l    d3,a1                Destination is IO buffer
  670.         move.l    UD_CopySect(a2),a2        Get best copy function
  671.         jsr    (a2)                Copy data into IOBuffer
  672.  
  673. 30$        movem.l    (a7)+,d2-d3/a2/a5
  674.         rts
  675.  
  676.  
  677. *-------------------------------------------------------*
  678. *
  679. *  CopySect  Copy one uncoded sector from one place to another using the CPU or the Exec function
  680. *
  681. *    Input:    a0    Source
  682. *        a1    Destination
  683. *        a3    TDU_
  684. *        a6    TDD_
  685. *
  686.  
  687.         ifne    TD_SECTOR-512
  688.         FAIL    Algorithm not properly adjusted for value of TD_SECTOR        
  689.         endc
  690.  
  691. CopySectCPU    movem.l    d2-d7/a2-a6,-(a7)        We use as much registers as possible, sort of burst mode
  692.         moveq.l    #9,d0                Init loop counter
  693. 10$        movem.l    (a0)+,d1-d7/a2-a6        Load 48 bytes
  694.         movem.l    d1-d7/a2-a6,(a1)        Store 48 bytes
  695.         add.w    #48,a1                With movem no ..,(a1)+ mode
  696.         dbra    d0,10$                Loop..
  697.         movem.l    (a0)+,d1-d7/a2            Still 32 bytes to do
  698.         movem.l    d1-d7/a2,(a1)
  699.         movem.l    (a7)+,d2-d7/a2-a6
  700.         rts
  701.  
  702. CopySectExec    move.l    #TD_SECTOR,d0            Size of copy
  703.         move.l    a6,-(a7)
  704.         move.l    TDD_SysBase(a6),a6
  705.         LibCall    CopyMem                DMA copy function
  706.         move.l    (a7)+,a6
  707.         rts
  708.         
  709.  
  710. *********************************************************
  711. *
  712. *  Auto motor off and update extensions
  713. *
  714. *  There are two events that set UD_Update to UPDATECOUNT.  The internal motor on command
  715. *  and a CMD_WRITE to a track.  The set after a write is done in TDE_Actual, a read extension.
  716. *  After the elapse of the taskloop timer this counter is decremented.  If it reaches zero,
  717. *  the changed-bit of the trackbuffer is tested, and if set, the buffer is written to disk.
  718. *  Then the motor is switched off.
  719. *
  720. *  Input:    a3    TDU_
  721. *        a6    TDD_
  722. *
  723.         
  724.  
  725. SetUpdCnt    move.l    d2,-(a7)            Just adapt to function termination
  726.  
  727. *--    Set/start update counter when motor is switched on
  728.  
  729. TDE_SetUpdCnt    ;Continuation of the motor switch routine
  730.  
  731.         btst.b    #CIAB_DSKMOTOR,TDU_CiabPb(a3)    Current motor state (inverted)
  732.         bne.s    10$                Motor is (switched) off..
  733.         move.l    TDU_TCB+TC_Userdata(a3),a0    Lea UnitData structure
  734.         move.w    #UPDATECOUNT,UD_Update(a0)    Init counter with number of iterations before updating
  735. 10$        move.l    (a7)+,d2            %
  736.         rts    ;                %
  737.         
  738. *--    Decrement update counter and take action upon elapse
  739.         
  740. TDE_CheckUpdate    ;Continuation of the taskloop timer
  741.  
  742. CU_        move.l    (a7)+,a6            %
  743.         btst.b    #B_UPDATE,UNIT_pad(a3)        Function in use?
  744.         beq.s    CU_Rtn30            No..
  745.  
  746.         movem.l    a2/a4,-(a7)
  747.         move.l    TDU_TCB+TC_Userdata(a3),a4    Lea UnitData structure
  748.         move.w    UD_Update(a4),d0        Down counter
  749.         beq.s    CU_Rtn20            Zero, nothing to do
  750.         subq.w    #1,d0                Decrement, now zero?
  751.         bne.s    CU_Rtn10            No, still nothing to do..
  752.         move.l    TDU_DiskBuf(a3),a2        Yes, current trackbuffer
  753.         btst.b    #0,TB_ChgFlag(a2)        Changed without been written to disk?
  754.         beq.s    CU_MotorOff            No, just switch motor off..
  755.         bsr    TDR_WriteTrack            Yes, write buffer to disk
  756.         tst.l    d0                Error?
  757.         bne.s    CU_MotorOff            Yes, but we don't care, skip clearing update-bit..
  758.         bclr.b    #0,TB_ChgFlag(a2)        Updated now
  759. CU_MotorOff    moveq.l    #0,d0                Switch motor off
  760.         bsr    TD_SwitchMotor            A462
  761.         moveq.l    #0,d0
  762.  
  763. CU_Rtn10    move.w    d0,UD_Update(a4)        
  764. CU_Rtn20    movem.l    (a7)+,a2/a4
  765. CU_Rtn30    rts    ;                %
  766.         
  767.  
  768. *********************************************************
  769. *
  770. *  NoClick extentions
  771. *
  772. *  Input:    a3    TDU_
  773. *        a6    TDD_
  774. *
  775.  
  776. TDE_NoClick    ;This routine is called instead of "bchg.b #CIAB_DSKDIREC,TDU_CiabPb(a3)"
  777.         
  778.         btst.b    #B_NOCLICK,UNIT_pad(a3)        Do we use this feature?
  779.         bne.s    10$                Yes..
  780.         bchg.b    #CIAB_DSKDIREC,TDU_CiabPb(a3)    No, change direction bit in cia B image
  781.         rts
  782. 10$        bset.b    #CIAB_DSKDIREC,TDU_CiabPb(a3)    Set direction bit to outwards in cia B image
  783.         rts
  784.  
  785.  
  786. *********************************************************
  787. *
  788. *  ReadOnly extentions
  789. *
  790. *  We can modify here the protect status of the disk
  791. *
  792. *  Input:    a3    TDU_
  793. *        a6    TDD_
  794. *
  795.  
  796. TDE_WriteProt    ;This routine is called instead of "btst.b #CIAB_DSKPROT,_ciaa+ciapra"
  797.  
  798. WP_        btst.b    #B_READONLY,UNIT_pad(a3)    Is this drive readonly?
  799.         bne.s    WP_ReadOnly            Yes..
  800.         btst.b    #CIAB_DSKPROT,_ciaa+ciapra    No, but perhaps this disk?
  801.         rts
  802.  
  803. TDE_WriteProt1    ;This routine is called instead of "btst.b #CIAB_DSKPROT,d2"
  804.  
  805.         btst.b    #B_READONLY,UNIT_pad(a3)    Is this drive readonly?
  806.         bne.s    WP_ReadOnly            Yes..
  807.         btst    #CIAB_DSKPROT,d2        No, but perhaps this disk?
  808.         rts
  809.  
  810. WP_ReadOnly    cmp.l    d0,d0                Set zero bit, meaning write protected
  811.         rts
  812.  
  813.  
  814. *********************************************************
  815. *
  816. *  RepairTrack
  817. *
  818. *  We will read the track in a large buffer.  This read is so big that there will be
  819. *  an unbroken track in the buffer.  If we find a valid sector address in this unbroken
  820. *  track, we can calculate the position of the track in the buffer.
  821. *
  822. *  Input:    a2    TD's trackbuffer
  823. *        a3    TDU_
  824. *        a6    TDD_
  825. *
  826. *  Usage:    a4    UD_
  827. *        a5    SB_
  828. *
  829.  
  830. RepairTrack    ;Called from an in place extension of TD's ReadTrack subroutine
  831.  
  832. RT_        movem.l d3/a4-a5,-(a7)
  833.         move.l    TDU_TCB+TC_Userdata(a3),a4    Lea UnitData structure
  834.         bsr    ObtainBuffer
  835.         move.l    a0,a5                Extra large read buffer
  836.         moveq.l #-1,d0                Motor on
  837.         bsr    TD_SwitchMotor            A462
  838.         lea.l    SB_Data(a5),a0            Begin of data in buffer
  839.         move.l    a0,SB_Begin(a5)
  840.         lea.l    (2*SPT-1)*SE_SIZE+GAPSIZE(a0),a0 Add size we search in for syncs
  841.         move.l    a0,SB_End(a5)
  842.         move.w    #BADTRACKBITS,UD_SavedL(a4)    Init log restored labels
  843.         move.w    #BADTRACKBITS,UD_SavedD(a4)    Init log restored data
  844.         moveq.l #4,d3                Init retry count
  845.  
  846. RT_SalveLoop    lea.l    SB_Data(a5),a0            Destination for disk-read
  847.         move.l    #2*SPT*SE_SIZE+GAPSIZE,d0    Number of bytes to read
  848.         bsr    TD_ReadDisk            A524 Read d0 bytes into (a0)
  849.         tst.l    d0                DiskChange?
  850.         beq.s    10$                No..
  851.         move.b    d0,TB_FirstSec(a2)        Yes, store error in trackbuffer for TD
  852.         bra.s    RT_Rtn                Leave..
  853. 10$        clr.w    SB_CorrectTrk(a5)        Reset counter of headers with good tracknumber
  854.         clr.w    SB_WrongTrk(a5)            Reset counter of headers with wrong tracknumber
  855.         bsr    Salve                Analyse the buffer and save what is possible
  856.         beq.s    RT_Rtn                All sectors and labels salved
  857.         move.w    SB_CorrectTrk(a5),d0        How many times did we encounter good tracknumbers
  858.         cmp.w    SB_WrongTrk(a5),d0        And how many bad?
  859.         bpl.s    20$                More good..
  860.         subq.l    #1,d3                Drive restore: just subtract one
  861.         ble.s    RT_Rtn                Retries completed, quit..
  862.         move.w    #-1,TDU_PTrack(a3)        Set current track to "Unknown"
  863.         moveq.l #0,d0
  864.         move.w    TDU_XTrack(a3),d0        Get track number we want
  865.         bsr    TD_Seek                A3DA Drive restore and seek
  866.         bra.s    RT_SalveLoop            Try again to salve the track
  867. 20$        subq.l    #2,d3                No restore, we read the correct track already, subtract two
  868.         bhi.s    RT_SalveLoop            Retries not yet completed, loop..
  869.  
  870. *
  871. *  We could write a track back to disk if it is completely recovered, but diskcopy or
  872. *  Disksalv can do the job.  We leave the track unchanged so investigation is still possible.  
  873. *  If YOU want to write it back you must build new sectorheaders in the recovered track
  874. *  and mark the track as being changed and remove my name from this program.
  875. *
  876.  
  877. RT_Rtn        bsr    ReleaseBuffer            Free buffer for usage by other TD tasks and functions
  878.         movem.l (a7)+,d3/a4-a5
  879.         rts
  880.  
  881. *-------------------------------------------------------*
  882. *
  883. *  Salve
  884. *
  885. *  We search for a sync.  If found we try to get a reliable sector address from the
  886. *  succeeding data.  This address tells us how much and the position of the track preceding
  887. *  this sector.     We try to recover these sectors if we did not already.     The area after the
  888. *  found sector is also checked for sector presence, but if no success search will continue
  889. *  from the found sync.
  890. *
  891. *  Input:    a2    TB_
  892. *        a3    TDU_
  893. *        a4    UD_
  894. *        a5    SB_
  895. *
  896. *  Usage:    d2    Scratch
  897. *        d5    SE_      Pointer to sector in imaginary track
  898. *        d6    SE_      Pointer to sector of last detected sync
  899. *        d7    Shiftfactor
  900. *
  901. *  Return:    d0    Pattern of bad labels and sectors
  902. *
  903.  
  904.  
  905. Salve
  906. ST_        movem.l d2-d3/d5-d7,-(a7)
  907.         subq.l    #HE_SIZE,a7            Four bytes local storage
  908.  
  909. *--    Lower priority during Salve
  910.  
  911.         moveq.l    #-2,d0                Lower than the standard user pri
  912.         bsr    SetTDPri            
  913.         move.b    d0,d3                Keep former priority
  914.  
  915.         move.l    SB_Begin(a5),d6            Begin of buffer
  916.         subq.l    #8,d6                Undo next instruction
  917.  
  918. *--    Scan buffer for syncs.    If found, test it for a valid header.
  919.  
  920. ST_SearchLoop    addq.l    #8,d6                Point to word past previous sync found
  921.         move.l    SB_End(a5),d0            End of search area
  922.         sub.l    d6,d0                Minus begin of search area is search size
  923.         ble    ST_EndSearch            End of buffer reached..
  924.         move.l    d6,a0                Actual begin of search
  925.         bsr    ST_SearchSync            Search next sync on this track
  926.         bmi    ST_EndSearch            No sync found, leave..
  927.         subq.l    #6,a0                Point to begin of potential sector
  928.         move.l    a0,d6                Keep potential sector found
  929.         bsr    ST_GetHeader            Test validity and decode header
  930.         ble.s    ST_SearchLoop            Not valid
  931.  
  932. *--    We have a sector header.  Figure a track around it.
  933.  
  934.         move.l    d0,(a7)                Local header for loop control
  935.         moveq.l #SPT,d0                Number of sectors per track
  936.         sub.b    HE_ToGap(a7),d0            Subtract ahead of us, leaves us with number of sectors before us
  937.         sub.b    d0,HE_SecNo(a7)            Set number of first sector, still positive?
  938.         bpl.s    10$                Yes..
  939.         add.b    #SPT,HE_SecNo(a7)        No, wrap
  940. 10$        move.b    #SPT,HE_ToGap(a7)        New gap countdown
  941.         mulu    #SE_SIZE,d0            Convert number of sectors to bytes before our position
  942.         move.l    d6,d5                Pointer to present sector
  943.         sub.l    d0,d5                Pointer to first potential sector
  944.  
  945. *--    Scan imaginary track for storable sectors
  946.  
  947. ST_TrackLoop    cmp.l    SB_Begin(a5),d5            Are we before begin of the buffer?
  948.         bmi    ST_NextSector            Yes, next sector..
  949.         cmp.l    SB_End(a5),d5            Are we past the end of the buffer?
  950.         bpl.s    ST_SearchLoop            Yes, stop with this track..
  951.         move.b    HE_SecNo(a7),d0            Sector number
  952.         move.l    UD_SavedL(a4),d1        Log of stored labels and sectors
  953.         beq    ST_AllSaved            All stored, leave this routine..
  954.         btst    d0,d1                Is the data of this sector already stored?
  955.         bne.s    ST_SaveSector            No, try to..
  956.         swap    d1                Yes, test the label
  957.         btst    d0,d1                This label aready saved?
  958.         beq    ST_NextSector            Yes, try next sector in our imaginary track..
  959.  
  960. *--    Try to store as much as possible from the sector d5 is pointing to.
  961.  
  962. ST_SaveSector    move.l    d5,a0                Ea of present sector
  963.         bsr    ST_GetHeader            Get its header if possible
  964.         bmi    ST_NextSector            Wrong track..
  965.         beq.s    ST_SaveData            No header, perhaps the sector's data is OK
  966.         cmp.l    (a7),d0                This MUST be the same or what?
  967.         bne    ST_VeryBad            Very bad indeed
  968.         move.l    d5,a0                Ea of present sector
  969.         lea.l    SE_SumD(a0),a0            Lea data checksum
  970.         bsr    ST_DecodeLong            Decode it
  971.         move.l    d0,d2                Keep for compare
  972.         move.l    #TD_SECTOR/2,d0            Size of data-part of sector in longs
  973.         bsr    ST_CheckSum            Calculate checksum over data
  974.         cmp.l    d2,d0                Same as found on disk?
  975.         beq.s    ST_CopySector            Yes, save to copy the complete sector..
  976.         move.b    HE_SecNo(a7),d0            No, but we have a valid header, the numbers are ok and if this
  977.         move.w    UD_SavedD(a4),d1            sector is not yet saved, we better still copy it
  978.         btst    d0,d1                Sector already saved?
  979.         beq    ST_SaveLabel            Yes, skip bad sector copy
  980.         bra.s    ST_LabelOK            We copy the sector, but skip the bitclear..
  981. ST_CopySector    move.b    HE_SecNo(a7),d0            Number of this sector
  982.         move.w    UD_SavedD(a4),d1        Data save-log
  983.         bclr    d0,d1                Set data saved
  984.         move.w    d1,UD_SavedD(a4)
  985. ST_LabelOK    move.b    HE_SecNo(a7),d0            Number of this sector
  986.         move.w    UD_SavedL(a4),d1        Label save-log
  987.         bclr    d0,d1                Set label saved
  988.         move.w    d1,UD_SavedL(a4)
  989.         ext.w    d0                Cnv sectornumber byte to word
  990.         mulu    #SE_SIZE,d0            To byte offset
  991.         lea.l    TB_Data(a2),a1            TD's buffer, begin of sectors
  992.         lea.l    SE_Label(a1,d0.l),a1        Lea destination of our data
  993.         move.l    d5,a0                Ea of present source sector
  994.         lea.l    SE_Label(a0),a0            Lea begin of part to copy
  995.         move.w    #((SSIZE/2)<<HSIZEBITS)+1,d0    Size of sector for blitter
  996.         move.w    #SSIZE,d2            Bytesize
  997.         bsr    BlitMove            Copy to TD's buffer
  998.         bra    ST_NextSector            Loop for next sector
  999.  
  1000. ST_SaveData    move.b    HE_SecNo(a7),d0            Sector number
  1001.         move.w    UD_SavedD(a4),d1        Saved data log
  1002.         btst    d0,d1                Data of this sector already saved?
  1003.         beq.s    ST_NextSector            Yes..
  1004.         move.l    d5,a0                Ea of present sector
  1005.         lea.l    SE_SumD(a0),a0            Lea data checksum
  1006.         bsr    ST_DecodeLong            Decode it
  1007.         move.l    d0,d2                Keep for compare
  1008.         move.l    #TD_SECTOR/2,d0            Size of data-part of sector in longs
  1009.         bsr    ST_CheckSum            Calculate checksum over data
  1010.         cmp.l    d2,d0                Same as found on disk?
  1011.         bne.s    ST_NextSector            No, no header and bad data, skip copy, next perhaps..
  1012.         moveq.l #0,d0
  1013.         move.b    HE_SecNo(a7),d0            Number of present sector
  1014.         move.w    UD_SavedD(a4),d1        Saved data log
  1015.         bclr    d0,d1                Set data of this sector saved
  1016.         move.w    d1,UD_SavedD(a4)
  1017.         mulu    #SE_SIZE,d0            Sector number times sectorsize to find offset in TD's buffer
  1018.         lea.l    TB_Data(a2),a1            TD's buffer, begin of sectors
  1019.         lea.l    SE_SumD(a1,d0.l),a1        Lea destination of our data
  1020.         move.l    d5,a0                Ea of source sector
  1021.         lea.l    SE_SumD(a0),a0            Lea Data checksum, begin of copy to TD's buffer
  1022.         move.w    #((DSIZE/2)<<HSIZEBITS)+1,d0    Size of datapart and its checksum ready for the blitter
  1023.         move.w    #DSIZE,d2            Bytesize of block
  1024.         bsr    BlitMove            Copy to TD's buffer
  1025.         bra.s    ST_NextSector            Continue loop..
  1026.  
  1027.  
  1028. ST_SaveLabel    ;move.b HE_SecNo(a7),d0            Present sector number
  1029.         move.w    UD_SavedL(a4),d1        Saved labels log
  1030.         bclr    d0,d1                We have a good one here
  1031.         beq.s    ST_NextSector            Was already saved, continue..
  1032.         move.w    d1,UD_SavedL(a4)        Nice, we can save a label
  1033.         ext.w    d0
  1034.         mulu.w    #SE_SIZE,d0            To byte offset
  1035.         lea.l    TB_Data(a2),a1            Lea begin of sectors
  1036.         lea.l    SE_Label(a1,d0.l),a1        Lea of label in destination sector in TD's buffer
  1037.         move.l    d5,a0                Ea of present sector
  1038.         lea.l    SE_Label(a0),a0            Lea label in source sector
  1039.         move.w    #((LSIZE/2)<<HSIZEBITS)+1,d0    Size of label ready for the blitter
  1040.         moveq.l #LSIZE,d2            Bytesize of block to move
  1041.         bsr    BlitMove            Move label to Trackdisks buffer
  1042.         ;bra.s    ST_NextSector            Continue loop..
  1043.  
  1044. *--    Track-scan loop control.
  1045.  
  1046. ST_NextSector    move.b    HE_SecNo(a7),d0            Sector number
  1047.         addq.b    #1,d0                Next sector
  1048.         cmp.b    #SPT,d0                Must we wrap?
  1049.         bcs.b    10$                No..
  1050.         moveq.l #0,d0                Yes, sector 0
  1051. 10$        move.b    d0,HE_SecNo(a7)
  1052.         add.l    #SE_SIZE,d5            Present sector pointer to next sector
  1053.         subq.b    #1,HE_ToGap(a7)            Decrement remaining sectors in our track, any left?
  1054.         bhi    ST_TrackLoop            Yes, process it..
  1055.         bra    ST_SearchLoop            No, we are ready with our track, try to find a new one..
  1056.  
  1057. ST_EndSearch
  1058. ST_AllSaved    move.l    UD_SavedL(a4),d0
  1059.  
  1060. ST_Rtn        exg.l    d3,d0                Former priority and keep pattern
  1061.         bsr    SetTDPri            Reset to original value
  1062.         addq.l    #HE_SIZE,a7            Clean up local
  1063.         move.l    d3,d0                Return proper condition codes
  1064.         movem.l (a7)+,d2-d3/d5-d7
  1065.         rts
  1066.  
  1067. ST_VeryBad    move.l    #BADTRACKBITS<<16+BADTRACKBITS,d0 Assume all labels and sectors to be unreliable
  1068.         move.l    d0,UD_SavedL(a4)
  1069.         bra.s    ST_Rtn
  1070.  
  1071.  
  1072. *-------------------------------------------------------*
  1073. *
  1074. *  GetHeader
  1075. *
  1076. *  Subroutine for Salve.  Test validity of the first part of a Trackdisk sector.  Set sector
  1077. *  address in SB_Header and return in d0 if valid.  Update statistics regarding tracknumber.
  1078. *  Return wrong track as a special case.
  1079. *
  1080. *  Input:    d7    Shift factor
  1081. *        a0    SE_
  1082. *        a2    TB_
  1083. *        a5    SB_
  1084. *
  1085. *  Return:    d0    Header, -1 if track wrong, 0 if other error.
  1086. *        a0    Ea of SE_Label
  1087. *
  1088.  
  1089. ST_GetHeader    addq.l    #SE_Header,a0
  1090.         moveq.l #HE_SIZE/2+TD_LABELSIZE/2,d0    Size of checksum area (longs)
  1091.         bsr    ST_CheckSum            Calculate checksum
  1092.         move.l    d0,-(a7)            Keep checksum
  1093.         bsr    ST_DecodeLong            Decode it
  1094.         cmp.l    (a7)+,d0            The same?
  1095.         bne.s    ST_BadHeader            No..
  1096.         add.w    #(SE_Header-SE_SumD),a0        Lea header again
  1097.         bsr    ST_DecodeLong
  1098.         move.l    d0,(a5)                Make header available
  1099.         cmp.b    #DISKFORMAT,(a5)        Our format?
  1100.         bne.s    ST_BadHeader            No..
  1101.         move.w    TB_TrkNo(a2),d1            Track number under head
  1102.         cmp.b    HE_TrkNo(a5),d1            Same as in header?
  1103.         bne.s    ST_WrongTrack            No..
  1104.         addq.w    #1,SB_CorrectTrk(a5)        Yes, one for us
  1105.         rts
  1106.  
  1107. ST_WrongTrack    addq.w    #1,SB_WrongTrk(a5)        One for them
  1108.         moveq.l #-1,d0                Error (restore?)
  1109.         rts
  1110.  
  1111. ST_BadHeader    moveq.l #0,d0                Error
  1112.         rts
  1113.  
  1114. *-------------------------------------------------------*
  1115. *
  1116. *  DecodeLong
  1117. *
  1118. *  Get two longwords from shifted memory and decode them into one longword
  1119. *
  1120. *  Input:    d7    Shift factor
  1121. *        a0    Data source
  1122. *
  1123. *  Return:    d0    Decoded longword
  1124. *        a0    Proper aligned for next access
  1125. *
  1126.  
  1127. ST_DecodeLong    movem.l d2/d3,-(a7)
  1128.         moveq.l #16,d3                Shift modulus
  1129.         sub.l    d7,d3                Complementary shift number
  1130.         move.l    (a0)+,d0            Get 48 bits (long + max shift)
  1131.         move.w    (a0),d2
  1132.         lsl.l    d7,d0                Shift first 32 bits left
  1133.         lsr.w    d3,d2                Shift last 16 bits right
  1134.         or.w    d2,d0                Put them together into one longword
  1135.         move.l    (a0)+,d1            Get 48 bits (long + max shift)
  1136.         move.w    (a0),d2
  1137.         lsl.l    d7,d1                Shift first 32 bits left
  1138.         lsr.w    d3,d2                Shift last 16 bits right
  1139.         or.w    d2,d1                Put them together into one longword
  1140.         and.l    #$55555555,d0            Remove MFM bits
  1141.         and.l    #$55555555,d1
  1142.         lsl.l    #1,d0                Line up
  1143.         or.l    d1,d0                Melt
  1144.         movem.l (a7)+,d2/d3
  1145.         rts
  1146.  
  1147.  
  1148. *-------------------------------------------------------*
  1149. *
  1150. *  CheckSum
  1151. *
  1152. *  Calculate checksum over shifted memory
  1153. *
  1154. *  Input:    d0    Length in longs
  1155. *        d7    Shift factor
  1156. *        a0    Begin of block
  1157. *
  1158. *  Return:    d0    Checksum
  1159. *        a0    Aligned to begin of next block
  1160. *
  1161.  
  1162. ST_CheckSum    movem.l d2/d3,-(a7)
  1163.         moveq.l #-1,d1                Build mask for first access
  1164.         lsr.l    d7,d1                Shift mask
  1165.         move.l    (a0)+,d2            Get part of first long
  1166.         and.l    d1,d2                Mask non-involved bits
  1167.         subq.l    #2,d0
  1168. 10$        move.l    (a0)+,d3            Get longs
  1169.         eor.l    d3,d2                Checksum algorithm
  1170.         dbra    d0,10$                Loop
  1171.         move.l    (a0),d3                Get last part of last long
  1172.         not.l    d1                Flip mask
  1173.         and.l    d1,d3                Mask non-involved bits
  1174.         eor.l    d3,d2                Checksum algorithm
  1175.         rol.l    d7,d2                Unshift
  1176.         and.l    #$55555555,d2            Select relevant bits
  1177.         move.l    d2,d0                Checksum
  1178.         movem.l (a7)+,d2/d3
  1179.         rts
  1180.  
  1181. *-------------------------------------------------------*
  1182. *
  1183. *  SearchSync
  1184. *
  1185. *  Search for a Sync. If found, return its address on word boundary and
  1186. *  how many bits it is shifted to the right. (max 15)
  1187. *
  1188. *  Input:    d0.w    Number of bytes to check
  1189. *        a0    Start address to search
  1190. *
  1191. *  Return:    d0.w    Bytes left
  1192. *        d7    Bitshift
  1193. *        a0    Sync
  1194. *
  1195.  
  1196. ST_SearchSync    lsr    #1,d0                Bytecount to wordcount
  1197. ST_SSLoop    move.w    (a0)+,d1
  1198.         cmp.w    #SYNCSYNC>>0,d1
  1199.         beq.s    ST_Found0
  1200.         cmp.w    #SYNCSYNC>>1,d1
  1201.         beq.s    ST_Found1
  1202.         cmp.w    #SYNCSYNC>>2,d1
  1203.         beq.s    ST_Found2
  1204.         cmp.w    #SYNCSYNC>>3,d1
  1205.         beq.s    ST_Found3
  1206.         cmp.w    #SYNCSYNC>>4,d1
  1207.         beq.s    ST_Found4
  1208.         cmp.w    #SYNCSYNC>>5,d1
  1209.         beq.s    ST_Found5
  1210.         cmp.w    #SYNCSYNC>>6,d1
  1211.         beq.s    ST_Found6
  1212.         cmp.w    #SYNCSYNC>>7,d1
  1213.         beq.s    ST_Found7
  1214.         cmp.w    #SYNCSYNC>>8,d1
  1215.         beq.s    ST_Found8
  1216.         cmp.w    #SYNCSYNC>>9,d1
  1217.         beq.s    ST_Found9
  1218.         cmp.w    #SYNCSYNC>>10,d1
  1219.         beq.s    ST_Found10
  1220.         cmp.w    #SYNCSYNC>>11,d1
  1221.         beq.s    ST_Found11
  1222.         cmp.w    #SYNCSYNC>>12,d1
  1223.         beq.s    ST_Found12
  1224.         cmp.w    #SYNCSYNC>>13,d1
  1225.         beq.s    ST_Found13
  1226.         cmp.w    #SYNCSYNC>>14,d1
  1227.         beq.s    ST_Found14
  1228.         cmp.w    #SYNCSYNC>>15,d1
  1229.         beq.s    ST_Found15
  1230.         dbra    d0,ST_SSLoop            Loop d0 words
  1231. ST_SSRtn    subq.l    #2,a0
  1232. ST_SSRtn10    lsl.w    #1,d0                Wordcount to bytecount
  1233.         rts
  1234.  
  1235. ST_Found0    moveq.l #0,d7
  1236.         bra.s    ST_SSRtn10
  1237. ST_Found1    moveq.l #1,d7
  1238.         bra.s    ST_SSRtn
  1239. ST_Found2    moveq.l #2,d7
  1240.         bra.s    ST_SSRtn
  1241. ST_Found3    moveq.l #3,d7
  1242.         bra.s    ST_SSRtn
  1243. ST_Found4    moveq.l #4,d7
  1244.         bra.s    ST_SSRtn
  1245. ST_Found5    moveq.l #5,d7
  1246.         bra.s    ST_SSRtn
  1247. ST_Found6    moveq.l #6,d7
  1248.         bra.s    ST_SSRtn
  1249. ST_Found7    moveq.l #7,d7
  1250.         bra.s    ST_SSRtn
  1251. ST_Found8    moveq.l #8,d7
  1252.         bra.s    ST_SSRtn
  1253. ST_Found9    moveq.l #9,d7
  1254.         bra.s    ST_SSRtn
  1255. ST_Found10    moveq.l #10,d7
  1256.         bra.s    ST_SSRtn
  1257. ST_Found11    moveq.l #11,d7
  1258.         bra.s    ST_SSRtn
  1259. ST_Found12    moveq.l #12,d7
  1260.         bra.s    ST_SSRtn
  1261. ST_Found13    moveq.l #13,d7
  1262.         bra.s    ST_SSRtn
  1263. ST_Found14    moveq.l #14,d7
  1264.         bra.s    ST_SSRtn
  1265. ST_Found15    moveq.l #15,d7
  1266.         bra.s    ST_SSRtn
  1267.  
  1268.  
  1269. *-------------------------------------------------------*
  1270. *
  1271. *  BlitMove
  1272. *
  1273. *  Move a block of data from source to destination and shift it left by some bits.
  1274. *
  1275. *  Input:    d0.w    Blitsize ready to pass to the blitter
  1276. *        d2.w    Bytesize of block to move
  1277. *        d7.w    Shift factor: number of bits that memory IS shifted to the right
  1278. *        a0    Source
  1279. *        a1    Destination
  1280. *        a3    TDU_
  1281. *        a6    TDD_
  1282. *
  1283. *  In linear mode the blitter can move at most 2^10 (1024) words. Therefore we use  its
  1284. *  rectancular mode. We can set the horizontal size to 1 to 128 words, thus limiting our
  1285. *  blit to multiples of these.
  1286.  
  1287. BlitMove
  1288. BM_        movem.l d3-d5/a2,-(a7)
  1289.  
  1290.         move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  1291.         lea.l    UD_BlitNode(a2),a2        Lea extended blitnode
  1292.  
  1293. *
  1294. *  We use the blitter in ascending mode. Then the blitter performs shifts to the right.
  1295. *  Therfore we translate our order to shift left into shift right.  IF we shift, and we
  1296. *  stick to our blitsize, we loose some bits. This is because we express in blitsize
  1297. *  the size of the track in words instead of bits.  If these bits do not begin on a
  1298. *  word-boundary they do not end either.  Because the blitter can move at most 1024
  1299. *  blocks of 1 to 128 words, and we do not determine the blocksize (the calling routine is),
  1300. *  we take care of this word by hand (the cpu).
  1301. *
  1302.         move.l    d7,d4                Shiftfactor (to left)
  1303.         neg.w    d4                We want 16 minus shift results in requested shift to right, zero?
  1304.         beq.s    10$                Yes, no shift..
  1305.         subq.l    #2,a1                Destination one word lower
  1306.         move.w    (a1),d3                Keep first word to restore after blit
  1307.         move.l    -2(a0,d2.w),d5            Get last two words of block (out of reach of the blitter)
  1308.         lsl.l    d7,d5                Do the shift of the last word here
  1309.         swap.w    d5                D5 holds now the last word
  1310. 10$        move.w    d0,bn_blitsize(a2)        The calling routine has aready assembled the correct value
  1311.         moveq.l #BSHIFTSHIFT,d0            Shift shift factor 12 bits left, thus clearing all other
  1312.         lsl.w    d0,d4                bits: no fill, ascending and area mode
  1313.         move.w    d4,TSBN_C1(a2)            Prepared blitter command
  1314.         move.l    a0,TSBN_P1(a2)            Source
  1315.         move.l    a1,TSBN_P2(a2)            Destination
  1316.         lea.l    BF_BM10(pc),a0            Lea blitter function
  1317.         move.l    a0,bn_function(a2)        Function into blitnode
  1318.         move.l    a2,a1                Pointer to our blitnode
  1319.         move.l    a6,-(a7)
  1320.         move.l    TDD_GfxBase(a6),a6        The graphics library coordinates blitter usage
  1321.         LibCall QBlit                Control is returned immedately so we must wait here
  1322.         move.l    (a7)+,a6
  1323.         bsr    TD_WaitTDPort            A70A Wait for a message we sent to ourself from within Gfx
  1324.         tst.w    TSBN_C1(a2)            Shift not zero?: Did we modify the destination pointer?
  1325.         beq.s    BM_Rtn                No, blit fitted in word boundary..
  1326.         move.l    TSBN_P2(a2),a0            Yes, get destination (pointing one word earlier)
  1327.         move.w    d3,(a0)                Restore original value of word before desired destination
  1328.         move.w    d5,0(a0,d2.w)            Last word which was out of reach of the blitter
  1329. BM_Rtn        movem.l (a7)+,d3-d5/a2
  1330.         rts
  1331.  
  1332.  
  1333. *********************************************************
  1334. *
  1335. *  CMD_READ, CMD_WRITE extensions.
  1336. *
  1337. *  Following extensions are called or jumped to from within the main IO routine
  1338. *  in Trackdisk.  This routine must be modified to handle reads from salved tracks,
  1339. *  to allow non-chip IO buffers, an additional error check and an adaption for
  1340. *  the auto update function.
  1341. *
  1342.  
  1343. *-------------------------------------------------------*
  1344. *
  1345. *  TDE_CMD_RW
  1346. *
  1347. *  Do some additional inits for the main IO routine:
  1348. *  Clear UD_Actual valid flag.
  1349. *  Extra test for CMD_WRITE to protected disk.
  1350. *  Type of memory of IO buffer.
  1351. *
  1352.  
  1353. TDE_CMD_RW    ;Called from somewhere near the begining of the handling of CMD_READ and CMD_WRITE
  1354.  
  1355. CRW_        moveq.l    #0,d0
  1356.         move.l    d0,IO_ACTUAL(a2)        % Replaced instruction
  1357.         moveq.l    #-1,d2                Set Reg_Actual to not valid
  1358.         cmp.b    #CMD_WRITE,IO_COMMAND+1(a2)    Is this a write command?
  1359.         bne.s    20$                No..
  1360.         btst.b    #B_READONLY,UNIT_pad(a3)    Yes, on a simulated readonly drive?
  1361.         bne.s    10$                Yes, error..
  1362.         btst.b    #4,TDU_Flags(a3)        No, on a protected disk?
  1363.         beq.s    20$                No, write alowed..
  1364. 10$        move.b    #TDERR_WriteProt,IO_ERROR(a2)    Yes, set error
  1365.         bra.s    CRW_Rtn                Return non-zero
  1366. 20$        move.l    IO_DATA(a2),a1            IOBuffer
  1367.  
  1368. TestMem        move.l    a6,-(a7)
  1369.         move.l    TDD_SysBase(a6),a6
  1370.         LibCall    TypeOfMem            What sort of memory is this buffer
  1371.         btst    #MEMB_CHIP,d0            Chip?
  1372.         sne.b    d6                Set d6 if chip
  1373.         move.l    (a7)+,a6
  1374.         moveq.l    #0,d0                Return no error
  1375. CRW_Rtn        rts
  1376.  
  1377. *-------------------------------------------------------*
  1378. *
  1379. *  TDE_CheckBuf
  1380. *
  1381. *  There is an error in the track.  If the track is not salved, the tracknumber
  1382. *  is set to -1, as TD normally does.  But if the track is salved, the tracknumber
  1383. *  must stay valid.
  1384. *
  1385.  
  1386. TDE_CheckBuf    ;Called from "terminate with read error"
  1387.  
  1388.         cmp.b    #CMD_WRITE,IO_COMMAND+1(a1)    Write command to bad track?
  1389.         beq.s    10$                Yes, error..
  1390.         btst.b    #B_SALVE,UNIT_pad(a3)        No, is the track salved?
  1391.         bne.s    20$                Yes..
  1392. 10$        move.b    d0,IO_ERROR(a1)            % Set error in IORequest
  1393.         move.w    #-1,TB_TrkNo(a2)        % Invalidate tracknumber
  1394.         moveq.l    #0,d0                Return equal, meaning leave IO with error
  1395. 20$        rts
  1396.  
  1397.  
  1398. *-------------------------------------------------------*
  1399. *
  1400. *  TDE_ReadCheck
  1401. *
  1402. *  Adapt reads to error handling based on error flags for each sector apart.
  1403. *  Trackdisk sets the tracknumber in its trackbuffer to -1, meaning no valid track in
  1404. *  the buffer.  TD does this if it finds a TB_FirstSec larger than possible.  We have
  1405. *  prevented TD doing so if the salve function was enabled.  Then we check TD_FirstSec
  1406. *  each time TD_TrkNo would have been checked.  This enables us to access a faulty
  1407. *  trackbuffer.
  1408. *  Always copy data, but if bad, set IO_ERROR and remember IO_ACTUAL.
  1409. *
  1410.         
  1411. TDE_ReadCheck    ;Bra to here instead of TD_CmdRead
  1412.  
  1413.         cmp.b    #SPT,TB_FirstSec(a0)        Error in track?
  1414.         bcs    TD_CmdRead            A890 No, proceed..
  1415.     
  1416.         moveq.l    #0,d0                
  1417.         move.b    TDU_IOSector(a3),d0        Current sector number
  1418.         tst.l    d2                Reg_Actual, error already processed?
  1419.         bpl    TD_CmdRead10            Yes, continue transfers..
  1420.  
  1421.         move.l    TDU_TCB+TC_Userdata(a3),a1    No, lea UnitData structure
  1422.         move.l    UD_SavedL(a1),d1        Get pattern with bad sectors and labels
  1423.         btst    d0,d1                Faulting sector?
  1424.         bne.s    10$                Yes, set error..
  1425.         btst.b    #0,TDU_Flags(a3)        Label transfer?
  1426.         beq    TD_CmdRead10            A8A0 No, no error, continue transfers..
  1427.         swap.w    d1                Yes, label transfers, get label log
  1428.         btst    d0,d1                Error in label?
  1429.         beq    TD_CmdRead10            A8A0 No, continue transfers..
  1430. 10$        move.l    IO_ACTUAL(a2),d2        Error! Remember number of bytes transferred so far
  1431.         move.b    TB_FirstSec(a0),IO_ERROR(a2)    Set error in IORequest
  1432.         bra    TD_CmdRead10            A8A0 Continue transfers
  1433.  
  1434.  
  1435. *-------------------------------------------------------*
  1436. *
  1437. *  TDE_ChkActual
  1438. *
  1439. *  Because all sectors are transferred that are requested, the requesting program
  1440. *  must have some way to know how much of its buffer is filled with good data.
  1441. *  The size is kept in d2 and if valid (positive) this is passed to the requester.
  1442. *  If we handled a write in this command, the track was updated and TrackSalve
  1443. *  must be informed for its auto update function.
  1444. *  
  1445.  
  1446. TDE_ChkActual    ;On the way to subroutine Reply IORequest.
  1447.  
  1448.         tst.b    IO_ERROR(a1)            Error met during IO?
  1449.         beq.s    10$                No..
  1450.         tst.l    d2                Is Reg_Actual valid?
  1451.         bmi    TD_IOReply            No, continue subroutine Reply IORequest..
  1452.         move.l    d2,IO_ACTUAL(a1)        Enter number of transferred bytes until error
  1453.         bra    TD_IOReply            Continue subroutine Reply IORequest..
  1454. 10$        cmp.b    #CMD_WRITE,IO_COMMAND+1(a1)    Was this IO a write?
  1455.         bne    TD_IOReply            No..
  1456.         move.l    TDU_TCB+TC_Userdata(a3),a0    Yes, lea UnitData structure
  1457.         move.w    #UPDATECOUNT,UD_Update(a0)    (Re)set update counter
  1458.         bra    TD_IOReply            Continue subroutine Reply IORequest..
  1459.  
  1460.  
  1461. *********************************************************
  1462. *
  1463. *  Write extensions.
  1464. *
  1465. *  Write Trackdisks buffer to disk and check whether verify is enabled.     Do not verify if the
  1466. *  TD_WriteTrack returned an error.  Get the verify buffer and read the just written track into
  1467. *  it.    Tidy the buffer up and compare it with the just written.  In case of some error, display
  1468. *  a requester and rewrite if asked for.
  1469. *
  1470. *  Input:    a3    Trackdisk Unit structure
  1471. *        a6    Trackdisk device base
  1472. *
  1473. *  Return:    d0    Write error
  1474. *
  1475. *  Usage:    d2    Error
  1476. *        a2    Verify buffer
  1477. *        a4    Trackdisk buffer written to disk
  1478. *
  1479.  
  1480. TDR_WriteTrackF ;Inserted/replaced call from Format to write buffer to disk
  1481.  
  1482.         clr.b    TB_FirstSec(a0)            Format does not use and set this field
  1483.  
  1484. TDR_WriteTrack    ;Replaces TD_WriteTrack
  1485.  
  1486. WT_        bsr    MFMTrack            Ensure proper MFM-format
  1487. WT_Write    bsr    TD_WriteTrack            A958 Normal write track
  1488.         move.b    UNIT_pad(a3),d1
  1489.         and.w    #(F_VERIFY1+F_VERIFY0),d1    Verify on?
  1490.         bne.s    20$                Yes..
  1491. 10$        rts
  1492.  
  1493. 20$        tst.l    d0                Did TD_WriteTrack had an error?
  1494.         bne.s    10$                Yes, we do not verify..
  1495.  
  1496.         movem.l d2/d3/a2/a4,-(a7)
  1497.         move.w    d1,d3                Verify bits become read retry counter
  1498.         subq.w    #1,d3                Adapt to dbra .. instruction
  1499.         bsr    ObtainBuffer            Get buffer to read into from disk
  1500.         move.l    a0,a2
  1501. 30$        move.l    TDU_DiskBuf(a3),a4        The buffer which was written to disk
  1502.         move.l    a2,TDU_DiskBuf(a3)        The buffer into we will read from disk
  1503.         move.w    (a4),(a2)            Tracknumber
  1504.         moveq.l #1,d0                Motor on
  1505.         bsr    TD_SwitchMotor            A462
  1506.         moveq.l #0,d0
  1507.         move.w    (a2),d0                Tracknumber
  1508.         bsr    TD_Seek                A3DA Seek to it
  1509.         lea.l    TB_Data+4(a2),a0        Position in buffer to begin to read
  1510.         move.w    #(SPT+1)*SE_SIZE+GAPSIZE,d0    Size of read
  1511.         bsr    TD_ReadDisk            A524 Read from disk
  1512.         tst.l    d0                DiskChange?
  1513.         bne.s    50$                Yes, that is a verify error..
  1514.         move.w    TDU_XTrack(a3),d2        Keep current value
  1515.         move.w    (a4),TDU_XTrack(a3)        TD_NormTrack uses this value as the current track
  1516.         moveq.l #-1,d0                Tell (modified) TD_NormTrack to skip header revision
  1517.         bsr    TD_NormTrack            AFE2 Tidy the track up
  1518.         move.w    d2,TDU_XTrack(a3)        Restore original value
  1519.         move.l    a4,TDU_DiskBuf(a3)        TD's write buffer back into TD's global
  1520.         cmp.b    #SPT,d0                Error?
  1521.         bcc.s    40$                Yes..
  1522.         move.b    d0,TB_FirstSec(a2)        First sector in the verify buffer
  1523.         move.l    a2,a0                Verify buffer
  1524.         move.l    a4,a1                Original written buffer
  1525.         bsr    CompareTracks            Compare both buffers (they are not exactly the same)
  1526.         beq.s    WT_Rtn                No error..
  1527. 40$        dbra    d3,30$                Read retry?
  1528.  
  1529. *--    Let's request. TD has a 512 byte stack. Not enough to call Intuition..    But we have here a buffer of 26k!
  1530.  
  1531. 50$        moveq.l #0,d0                Motor off during request
  1532.         bsr    TD_SwitchMotor            A462
  1533.         add.w    #10000,a2            Make a little room for stack
  1534.         exg    a2,a7                Set a7 to the buffer
  1535.         move.w    TB_TrkNo(a4),d0            Tracknumber
  1536.         bsr    VerifyAlert            Display the requester
  1537.         move.l    a2,a7                TD's stack again
  1538. WT_Rtn        move.l    d0,d2                Answer of user: zero is ignore
  1539.         bsr    ReleaseBuffer            We do not need the verify buffer anymore
  1540.         move.l    d2,d0                Rewrite?
  1541.         movem.l (a7)+,d2/d3/a2/a4
  1542.         bne    WT_Write            The user wanted a rewrite..
  1543.         rts
  1544.  
  1545.  
  1546. *-------------------------------------------------------*
  1547. *
  1548. *  CompareTracks
  1549. *
  1550. *  Compare data in two trackbuffers.  A simple compare is not possible.     The data should be
  1551. *  the same but may be arranged differently.
  1552. *
  1553. *  Input:    a0    TB_ verify
  1554. *        a1    TB_ original
  1555. *
  1556. *  Return:    d0    Zero if buffers are the same, -1 in case of error
  1557. *
  1558.  
  1559. CompareTracks
  1560. CT_        move.l    a2,-(a7)
  1561.         move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  1562.         lea.l    UD_BlitNode(a2),a2        Lea extended blitnode
  1563.  
  1564.         moveq.l #0,d0                No error
  1565.         move.l    d0,TSBN_P3(a2)            Preset blitter return value
  1566.         
  1567.         sub.b    TB_FirstSec(a1),d0        Subtract first sector of the original buffer
  1568.         add.b    TB_FirstSec(a0),d0        Add first sector of the verify buffer
  1569.         bpl.s    10$                Positive..
  1570.         add.b    #SPT,d0                Wrap
  1571. 10$        move.w    d0,bn_blitsize(a2)        Number of sectors to compare the first time
  1572.         moveq.l    #SPT,d1                Total number of sectors
  1573.         sub.l    d0,d1                Number of remaining sectors to compare the second time
  1574.         mulu    #SE_SIZE,d1            Size of block to compare the second time
  1575.  
  1576.         lea.l    TB_Data(a1),a1            Begin of compare in the original buffer
  1577.         move.l    a1,TSBN_P0(a2)            Into blitnode
  1578.         lea.l    TB_Data(a0),a0            Begin of second compare in the verify buffer
  1579.         move.l    a0,TSBN_P2(a2)            Into blitnode
  1580.         add.l    d1,a0                Add size of second compare to find begin of first compare
  1581.         move.l    a0,TSBN_P1(a2)            Begin of first compare in the verify buffer into blitnode
  1582.  
  1583.         lea.l    BF_CMP10(pc),a0            First blitter compare function
  1584.         move.l    a0,bn_function(a2)        Into blitnode
  1585.         move.l    a2,a1                Blitnode 
  1586.         move.l    a6,-(a7)
  1587.         move.l    TDD_GfxBase(a6),a6        The graphics library coordinates blitter usage
  1588.         LibCall QBlit                Control is returned immedately so we must wait here
  1589.         move.l    (a7)+,a6
  1590.         bsr    TD_WaitTDPort            A70A Wait for a message we sent to ourself from within Gfx
  1591.  
  1592.         move.l    TSBN_P3(a2),d0            Return value of blitter compare function
  1593.         move.l    (a7)+,a2
  1594.         rts
  1595.  
  1596.  
  1597. *-------------------------------------------------------*
  1598. *
  1599. *  VerifyAlert    -  Notify user of the verity error and ask him what to do.
  1600. *
  1601. *  To do so, we use a requester with the choise to ignore the event (inherent in TD) or to
  1602. *  rewrite the track.  This is more complicated as it looks at first sight.  It would be
  1603. *  nice if an AutoRequest could be used (simple & small), but the idea behind write verify
  1604. *  requires an airtight approach.  If there is not enough memory to build the AutoRequest,
  1605. *  Intuition defaults to an Alert.  But if there is not enough memory to build the Alert,
  1606. *  Intuition simply returns FALSE.  As if the user selected "Ignore".  Useless for our
  1607. *  purposes.  So we have to build our own requester.  We have no window open, so we open a
  1608. *  window for just one use:  to show the requester.  A requester has the fe. ff feature to
  1609. *  block all input to the window.  Intuition permits all kinds of events to penetrate to
  1610. *  the SysRequest.  I do not know an easy way (we are patching TD, remember?) to get the same
  1611. *  result.  The other approach is to build the gadgets directly in the window.    Then we
  1612. *  receive all kind of events, including Left-Amiga-V and Left-Amiga-N.     Pity that DMouse
  1613. *  cannot see that we are requesting.  But otherwise we have no shortcuts.  So?
  1614. *
  1615. *  Input:    d0    Tracknumber
  1616. *        a3    TDU_
  1617. *        a6    TDD_
  1618. *
  1619. *  Return:    d0    TRUE for rewrite, FALSE for ignore
  1620. *
  1621. *  Usage:    d2    im_IAddress, Window fail and function result flag
  1622. *        d3    im_Class
  1623. *        d4    im_Code
  1624. *        a4    Window structure
  1625. *        a5/a6    IntuitionBase/SysBase
  1626. *
  1627.  
  1628.  
  1629. VerifyAlert
  1630. VA_        movem.l d2-d4/a2/a4/a5,-(a7)
  1631.  
  1632. *--    Insert head number in requester string
  1633.  
  1634.         moveq.l #'0'>>1,d1            Prepare for asci conversion
  1635.         lsr.b    #1,d0                Get head number in X-bit
  1636.         roxl.b    #1,d1                Make asci zero or one
  1637.         lea.l    TXT_HeadNr(pc),a0        Destination
  1638.         move.b    d1,(a0)                Store into requester string
  1639.  
  1640. *--    D0 now contains the cylinder number.  Convert via BCD to asci and store into string
  1641.  
  1642.         move.l    a7,a2                Predecrement pointer to local word
  1643.         clr.w    -(a7)                One word local
  1644.         moveq.l #7,d1                Binary 2 nibbles to 2 bcd nibbles conversion
  1645. 10$        move.l    a2,a0                Destination
  1646.         move.l    a2,a1                Destination
  1647.         lsl.b    #1,d0                Binary shift left
  1648.         abcd.b    -(a0),-(a1)            Bcd shift left
  1649.         dbra    d1,10$                Loop for eigth bits
  1650.  
  1651.         move.w    (a7)+,d1            Get bcd word
  1652.         lea.l    TXT_TrackNr(pc),a0        Destination
  1653.         move.b    d1,d0                Bcd value
  1654.         lsr.b    #4,d1                Next nibble
  1655.         or.b    #'0',d1                Convert to asci
  1656.         move.b    d1,(a0)+            Store in alert string
  1657.         and.b    #$0f,d0                Mask nibble
  1658.         or.b    #'0',d0                Convert to asci
  1659.         move.b    d0,(a0)                Store in alert string
  1660.  
  1661. *--    Unit number in string
  1662.  
  1663.         moveq.l #'0',d0                Asci first unit
  1664.         add.b    TDU_UnitNr(a3),d0        Unit number
  1665.         lea.l    TXT_UnitNr(pc),a0        Position in requester string
  1666.         move.b    d0,(a0)                Store unit number
  1667.  
  1668. *--    Open a window on the Workbench screen and show a requester in it.
  1669.  
  1670.         moveq.l #-1,d2                Set flag to requester failed
  1671.         move.l    TDU_TCB+TC_Userdata(a3),a0    Lea UnitData structure
  1672.         move.l    UD_TSControl(a0),a0        TSControl structure
  1673.         move.l    a6,-(a7)            Trackdisk device base
  1674.         move.l    TDD_SysBase(a6),a5        ExecBase
  1675.         move.l    TSC_IntuBase(a0),a6        Our starter got IntuitionBase already for us
  1676.         LibCall WBenchToFront            We open our window in the WB screen
  1677.         move.l    ib_FirstScreen(a6),a0        Get this screen
  1678.         move.w    sc_DetailPen(a0),d0        Get both screen pens.
  1679.         lea.l    TSCodeBegin(pc),a0        
  1680.         move.w    d0,IT_Body0-TSCodeBegin(a0)    Use normal pens for body texts
  1681.         move.w    d0,IT_Body1-TSCodeBegin(a0)
  1682.         move.b    d0,IMG_ReqOnOff-TSCodeBegin(a0)
  1683.         rol.w    #8,d0                Swap pens to get inversed texts
  1684.         move.w    d0,IT_Positive-TSCodeBegin(a0)    Use inversed display for gadget texts
  1685.         move.w    d0,IT_Negative-TSCodeBegin(a0)
  1686.         move.b    d0,IMG_GadOnOff-TSCodeBegin(a0)
  1687.         lea.l    NEW_Requester(pc),a0        NewWindow structure
  1688.         LibCall OpenWindow
  1689.         move.l    d0,a4                Window structure, success?
  1690.         beq.s    VA_NoReq            No..
  1691.  
  1692. *--    Wait for an answer of the user
  1693.  
  1694.         exg.l    a5,a6                SysBase in a6
  1695. VA_IDCMP_Loop    move.l    wd_UserPort(a4),a0        IDCMP message port
  1696.         LibCall WaitPort            Wait for a message from Intuition
  1697.         move.l    wd_UserPort(a4),a0        IDCMP message port
  1698.         LibCall GetMsg                Remove message from queue
  1699.         move.l    d0,a1
  1700.         move.l    im_Class(a1),d3            Keep Class
  1701.         move.l    im_IAddress(a1),d2        Keep message initiator
  1702.         move.l    im_Code(a1),d4            Keep Code AND Qualifier
  1703.         LibCall ReplyMsg            Message back to Intuition
  1704.  
  1705. *--    Perhaps the user clicked one of the gadgets
  1706.  
  1707.         cmp.l    #GADGETUP,d3            Gadget clicked?
  1708.         bne.s    VA_ChkRawkey            No, check keyboard shortcut
  1709.         lea.l    GAD_Negative(pc),a0        Get one of both message initiators
  1710.         sub.l    a0,d2                Set return value to zero if this gadget was clicked
  1711.         beq.s    VA_CloseReq            "Ignore" was clicked..
  1712.         moveq.l #1,d2                Not equal, other gadget must have been clicked, return positive
  1713.         bra.s    VA_CloseReq
  1714.  
  1715. *--    Perhaps the user pressed a 'B' or 'V'
  1716.  
  1717. VA_ChkRawkey    cmp.l    #RAWKEY,d3            Keyboard event?
  1718.         bne.s    VA_IDCMP_Loop            No, ignore message..
  1719.         and.w    #IEQUALIFIER_LCOMMAND,d4    Left-Amiga pressed?
  1720.         beq.s    VA_IDCMP_Loop            No, ignore..
  1721.         swap.w    d4                Select code field
  1722.         moveq.l #0,d2                Returnvalue for "Ignore"
  1723.         cmp.w    #$0035,d4            Keycode for 'B'
  1724.         beq.s    VA_CloseReq            Same, return ignore..
  1725.         moveq.l #1,d2                Returnvalue for "Rewrite"
  1726.         cmp.w    #$0034,d4            Keycode for 'V'
  1727.         bne.s    VA_IDCMP_Loop            Not what we want, ignore message..
  1728.  
  1729. *--    Get present position of the window and close it
  1730.  
  1731. VA_CloseReq    exg.l    a5,a6                IntuitionBase again
  1732.         lea.l    NEW_Requester(pc),a0        NewWindow structure
  1733.         move.l    wd_LeftEdge(a4),(a0)        Install present window position into new window
  1734.         move.l    a4,a0                Window structure
  1735.         LibCall CloseWindow
  1736. VA_NoReq    move.l    a6,a5                IntuitionBase
  1737.         move.l    (a7)+,a6            TD base
  1738.         move.l    d2,d0                Result
  1739.         bpl.s    VA_Rtn                Positive, user replied on requester..
  1740.  
  1741. *--    For some reason there was no requester, so bleep screens and blink drive led, return rewrite
  1742.  
  1743.         exg    a5,a6                Negative, no requester, get IntuBase
  1744.         sub.l    a0,a0                All screens
  1745.         LibCall DisplayBeep            Bleep
  1746.         exg    a5,a6                TD Base
  1747.         moveq.l #6,d2                Blink drive led 3 times
  1748. 10$        move.l    d2,d0                Get counter
  1749.         and.l    #1,d0                Select LSB (toggles)
  1750.         bsr.w    TD_SwitchMotor            A462 Motor on and off
  1751.         move.l    #200000,d0            Sleep for a while
  1752.         bsr.w    TD_Sleep            A4F0
  1753.         dbra    d2,10$                Loop
  1754.         moveq.l #-1,d0                Set rewrite as result
  1755.  
  1756. VA_Rtn        movem.l (a7)+,d2-d4/a2/a4/a5
  1757.         rts
  1758.  
  1759.  
  1760. *-------------------------------------------------------*
  1761. *
  1762. *  Requester data structures.
  1763. *
  1764. *  These structures have pointers to each other.  Therefore we cannot move them without making
  1765. *  adaptions.  We can do two things.  Normal relocation followed by an adaption after the move,
  1766. *  or not relocate at loadtime and perform complete relocation later.  We choose the latter
  1767. *  because this saves relocation info in the exe and the relocation routine is not
  1768. *  larger/smaller/easyer/harder.
  1769. *  Because the relocation table is not to be included in the resident structure, it is
  1770. *  physically placed somewhere at the end of this file.
  1771. *  The "Body text" is tied to the "positve text".  This saves us Intuprinting the requester text.
  1772. *  Because code is outgrowing already the pan, the font is fixed to topaz 8.  All calculations
  1773. *  regarding window size, gadget positions, text postitions are done by hand and here and now.
  1774. *
  1775. *  This code will be modified, but it contains no CPU instructions.
  1776. *
  1777.  
  1778. NEW_Requester    dc.w    0,0
  1779.         dc.w    242,55
  1780.         dc.b    -1,-1
  1781.         dc.l    GADGETUP+RAWKEY
  1782.         dc.l    WINDOWDEPTH+WINDOWDRAG+SIMPLE_REFRESH+NOCAREREFRESH+ACTIVATE
  1783. NEW_ReqGadget    dc.l    GAD_Positive-TSCodeBegin
  1784.         dc.l    0
  1785. NEW_ReqTitle    dc.l    TXT_VerTitle-TSCodeBegin
  1786.         dc.l    0,0
  1787.         dc.w    0,0,0,0
  1788.         dc.w    WBENCHSCREEN
  1789.  
  1790. GAD_Positive    dc.l    GAD_Negative-TSCodeBegin
  1791.         dc.w    26,35
  1792.         dc.w    82,16
  1793.         dc.w    GADGIMAGE+GADGHCOMP
  1794.         dc.w    RELVERIFY+ENDGADGET
  1795.         dc.w    BOOLGADGET+REQGADGET
  1796. GAD_PosRender    dc.l    IMG_Gadgets-TSCodeBegin
  1797.         dc.l    0
  1798. GAD_PosIText    dc.l    IT_Positive-TSCodeBegin
  1799.         dc.l    0
  1800.         dc.l    0
  1801.         dc.w    0
  1802.         dc.l    0
  1803.  
  1804. GAD_Negative    dc.l    0
  1805.         dc.w    134,35
  1806.         dc.w    82,16
  1807.         dc.w    GADGIMAGE+GADGHCOMP
  1808.         dc.w    RELVERIFY+ENDGADGET
  1809.         dc.w    BOOLGADGET+REQGADGET
  1810. GAD_NegRender    dc.l    IMG_Request-TSCodeBegin
  1811.         dc.l    0
  1812. GAD_NegIText    dc.l    IT_Negative-TSCodeBegin
  1813.         dc.l    0
  1814.         dc.l    0
  1815.         dc.w    0
  1816.         dc.l    0
  1817.  
  1818. IMG_Request    dc.w    -130,-23
  1819.         dc.w    234,41,0
  1820.         dc.l    0
  1821.         dc.b    0
  1822. IMG_ReqOnOff    dc.b    0
  1823. IMG_ReqNext    dc.l    IMG_Gadgets-TSCodeBegin
  1824.  
  1825. IMG_Gadgets    dc.w    0,0
  1826.         dc.w    82,16,0
  1827.         dc.l    0
  1828.         dc.b    0
  1829. IMG_GadOnOff    dc.b    0
  1830.         dc.l    0
  1831.  
  1832. IT_Positive    dc.b    0,0,RP_JAM2,0
  1833.         dc.w    13,4
  1834. IT_PosFont    dc.l    TA_Topaz8-TSCodeBegin
  1835. IT_PosText    dc.l    TXT_Positive-TSCodeBegin
  1836. IT_PosNext    dc.l    IT_Body0-TSCodeBegin
  1837.  
  1838. IT_Negative    dc.b    0,0,RP_JAM2,0
  1839.         dc.w    17,4
  1840. IT_NegFont    dc.l    TA_Topaz8-TSCodeBegin
  1841. IT_NegText    dc.l    TXT_Negative-TSCodeBegin
  1842.         dc.l    0
  1843.  
  1844. IT_Body0    dc.b    0,0,RP_JAM2,0
  1845.         dc.w    -14,-20                Relative to the positive gadget
  1846. IT_B0Font    dc.l    TA_Topaz8-TSCodeBegin
  1847. IT_B0Text    dc.l    TXT_Body0-TSCodeBegin
  1848. IT_B0Next    dc.l    IT_Body1-TSCodeBegin
  1849.  
  1850. IT_Body1    dc.b    0,0,RP_JAM2,0
  1851.         dc.w    -14,-11                Relative to the positive gadget
  1852. IT_B1Font    dc.l    TA_Topaz8-TSCodeBegin
  1853. IT_B1Text    dc.l    TXT_Body1-TSCodeBegin
  1854.         dc.l    0
  1855.  
  1856. TA_Topaz8    dc.l    TXT_FontName-TSCodeBegin
  1857.         dc.w    8
  1858.         dc.b    FS_NORMAL,0
  1859.  
  1860. TXT_VerTitle    dc.b    ' TrackSalve 1.3 ',0,0,0
  1861. TXT_FontName    dc.b    'topaz.font',0
  1862. TXT_Body0    dc.b    'Write verify error detected',0
  1863. TXT_Body1    dc.b    'on unit '
  1864. TXT_UnitNr    dc.b        'x, track '
  1865. TXT_TrackNr    dc.b             'xx, head '
  1866. TXT_HeadNr    dc.b                  'x',0
  1867.  
  1868. TXT_Positive    dc.b    'Rewrite',0
  1869. TXT_Negative    dc.b    'Ignore',0
  1870.  
  1871.         cnop    0,4
  1872.         
  1873.         
  1874. *********************************************************
  1875. *
  1876. *  ObtainBuffer  -  ReleaseBuffer
  1877. *
  1878. *  Handling of permission to use the buffer
  1879. *
  1880. *  Input:    a3    TDU_
  1881. *        a6    TDD_
  1882. *
  1883. *  Return:    a0    buffer
  1884. *
  1885.  
  1886. ObtainBuffer    move.l    a2,-(a7)
  1887.         move.l    TDU_TCB+TC_Userdata(a3),a2    Lea UnitData structure
  1888.         move.l    UD_TSControl(a2),a2        Lea TSControl structure
  1889.         lea.l    TSC_OwnBuffer(a2),a0        Lea Semaphore for buffer usage
  1890.         move.l    a6,-(a7)
  1891.         move.l    TDD_SysBase(a6),a6        Trackdisk's SysBase
  1892.         LibCall AttemptSemaphore        Try to lock buffer usage
  1893.         move.l    (a7)+,a6
  1894.         tst.l    d0                Locked?
  1895.         bne.s    10$                Yes..
  1896.         moveq.l #0,d0                No, motor off
  1897.         bsr    TD_SwitchMotor            A462
  1898.         lea.l    TSC_OwnBuffer(a2),a0        Lea Semaphore for buffer usage
  1899.         move.l    a6,-(a7)
  1900.         move.l    TDD_SysBase(a6),a6        Trackdisk's SysBase
  1901.         LibCall ObtainSemaphore            Wait for permission to use it
  1902.         move.l    (a7)+,a6
  1903. 10$        move.l    TSC_Buffer(a2),a0        The buffer itself
  1904.         move.l    (a7)+,a2
  1905.         rts
  1906.  
  1907.  
  1908. ReleaseBuffer    move.l    TDU_TCB+TC_Userdata(a3),a0    Lea UnitData structure
  1909.         move.l    UD_TSControl(a0),a0        Lea TSControl structure
  1910.         lea.l    TSC_OwnBuffer(a0),a0        Lea Semaphore for buffer usage
  1911.         move.l    a6,-(a7)
  1912.         move.l    TDD_SysBase(a6),a6        Trackdisk's SysBase
  1913.         LibCall ReleaseSemaphore
  1914.         move.l    (a7)+,a6
  1915.         rts
  1916.  
  1917.  
  1918. *********************************************************
  1919. *
  1920. *  SetTDPri
  1921. *
  1922. *  Change task priority of this Trackdisk task
  1923. *
  1924.  
  1925. SetTDPri    lea.l    TDU_TCB(a3),a1            Trackdisk's task structure
  1926.         move.l    a6,-(a7)
  1927.         move.l    TDD_SysBase(a6),a6
  1928.         LibCall    SetTaskPri
  1929.         move.l    (a7)+,a6
  1930.         rts
  1931.  
  1932.  
  1933. *********************************************************
  1934. *
  1935. *  QBlit functions.  Parameters are passed by the blitnode structure.
  1936. *  We have exclusive control over the blitter here.
  1937. *  NB!    This code is executed under control of other regimes. Behave well.
  1938. *
  1939. *  Input:    a0    Pointer to blitter
  1940. *        a1    Pointer to blitnode
  1941. *
  1942. *  Return:    d0    -1, meaning not ready
  1943. *
  1944.  
  1945. *-------------------------------------------------------*
  1946. *
  1947. *  Take a (faulting) MFM-word and convert it to BF (My name: Balanced Format):
  1948. *
  1949. *  Take the data bits (mask $5555), shift them right one bit, invert them,
  1950. *  and store them merged with the original databits back into the same
  1951. *  location.  Now we have the BF-format.
  1952. *
  1953.  
  1954. ;                                 __
  1955. BLITLF        set    ABC+ANBC+ANBNC+NANBNC        D=AC+BC
  1956. BLITUSE        set    SRCA+SRCB+DEST
  1957. SHIFTA        set    0<<ASHIFTSHIFT
  1958. SHIFTB        set    1<<BSHIFTSHIFT
  1959.  
  1960. CTL0        set    SHIFTA+BLITUSE+BLITLF
  1961. CTL1        set    SHIFTB                Ascending, Area
  1962.  
  1963. BF_MT10        bsr.s    BF_SetBlitMod
  1964.         move.l    TSBN_P0(a1),d1            Begin of block
  1965.         move.l    d1,bltapt(a0)            Into A
  1966.         move.l    d1,bltbpt(a0)            Into B
  1967.         move.l    d1,bltdpt(a0)            Begin of block into D
  1968.         move.w    #$5555,bltcdat(a0)        Datamask
  1969.         move.l    #CTL0<<16+CTL1,bltcon0(a0)    Instruct blitter its operation
  1970.         move.w    #((SE_SIZE/2)<<HSIZEBITS)+SPT,bltsize(a0)    Start blit
  1971.         lea.l    BF_MT20(pc),a0
  1972.         move.l    a0,bn_function(a1)        Next function    
  1973.         ;moveq    #-1,d0            
  1974.         rts
  1975.  
  1976. *-------------------------------------------------------*
  1977. *
  1978. *  Take a BF word and convert it to MFM:
  1979. *
  1980. *  Take a BF word, invert it, shift it left one bit, and AND it with
  1981. *  the original BF word. Now it is MFM.
  1982.  
  1983. ;                            _
  1984. BLITLF        set    NABC+NABNC            AB
  1985. BLITUSE        set    SRCA+SRCB+DEST
  1986. SHIFTA        set    1<<ASHIFTSHIFT
  1987. SHIFTB        set    0<<BSHIFTSHIFT
  1988.  
  1989. CTL0        set    SHIFTA+BLITUSE+BLITLF
  1990. CTL1        set    SHIFTB+BC1F_DESC        Descending: leftshifts
  1991.  
  1992. BF_MT20        move.l    TSBN_P1(a1),d1            End of block
  1993.         move.l    d1,bltapt(a0)            All blitter pointers to it
  1994.         move.l    d1,bltbpt(a0)        
  1995.         move.l    d1,bltdpt(a0)        
  1996.         move.l    #CTL0<<16+CTL1,bltcon0(a0)    Instruct blitter its operation
  1997.         move.w    #((SE_SIZE/2)<<HSIZEBITS)+SPT,bltsize(a0)    Start blit
  1998.         bra.s    BF_QuitBlit
  1999.         
  2000.  
  2001. *-------------------------------------------------------*
  2002. *
  2003. *  Copy source direct into destination
  2004. *
  2005.  
  2006. BLITLF    set    ABC+ABNC+ANBC+ANBNC            D=A
  2007. BLITUSE    set    SRCA+DEST
  2008. SHIFTA    set    0<<ASHIFTSHIFT
  2009. SHIFTB    set    0<<BSHIFTSHIFT
  2010.  
  2011. CTL0    set    SHIFTA+BLITUSE+BLITLF
  2012. CTL1    set    SHIFTB                    Ascending, Area mode
  2013.  
  2014. BF_ES10        bsr.s    BF_SetBlitMod
  2015.         move.l    TSBN_P0(a1),bltapt(a0)        Source
  2016.         move.l    TSBN_P1(a1),bltdpt(a0)        Destination
  2017.         move.l    #(CTL0<<16)+CTL1,bltcon0(a0)    Ascending, Area mode
  2018.         move.w    #((TD_SECTOR/2)<<HSIZEBITS)+1,bltsize(a0)    Start blit
  2019.         lea.l    BF_ES25(pc),a0            Next function
  2020.         move.l    a0,bn_function(a1)        
  2021.         rts
  2022.  
  2023.  
  2024. *-------------------------------------------------------*
  2025.  
  2026. BF_SetBlitMod    moveq.l    #0,d0
  2027.         move.l    d0,bltcmod(a0)            Clear c and b modulus
  2028.         move.l    d0,bltamod(a0)            Clear a and d modulus
  2029.         moveq.l    #-1,d0                Build mask
  2030.         move.l    d0,bltafwm(a0)            Set first and last word mask
  2031.         rts
  2032.         
  2033. BF_QuitBlit    lea.l    BF_End(pc),a0
  2034.         move.l    a0,bn_function(a1)        Next function    
  2035.         moveq.l    #-1,d0
  2036.         rts
  2037.         
  2038.         
  2039. *-------------------------------------------------------*
  2040. *
  2041. *  Copy the source block to the destination and shift it right one bit.
  2042. *
  2043.  
  2044. BLITLF    set    ABC+ABNC+ANBC+ANBNC            D=A
  2045. BLITUSE    set    SRCA+DEST                As memory input
  2046. SHIFTA    set    1<<ASHIFTSHIFT            
  2047. SHIFTB    set    0<<BSHIFTSHIFT
  2048.  
  2049. CTL0    set    SHIFTA+BLITUSE+BLITLF
  2050. CTL1    set    SHIFTB                    Ascending: shift right, Area mode
  2051.  
  2052. BF_ES20        bsr.s    BF_SetBlitMod
  2053. BF_ES25        move.l    TSBN_P2(a1),bltapt(a0)        Source pointer
  2054.         move.l    TSBN_P3(a1),bltdpt(a0)        Destination
  2055.         move.l    #CTL0<<16+CTL1,bltcon0(a0)    Instruct blitter its operation
  2056.         move.w    #((TD_SECTOR/2)<<HSIZEBITS)+1,bltsize(a0)    Start blit
  2057.         bra.s    BF_QuitBlit
  2058.  
  2059. *-------------------------------------------------------*
  2060. *
  2061. *  To decode we mask the first word, shift it left, and OR it with the masked second word.
  2062. *  This way we do it with the CPU. The blitter can perform this algorith: Shift the first
  2063. *  word by one bit, AND it with the inverted mask and OR it with the second word which is
  2064. *  ANDed with the true mask: D=((A>>1).NC)+BC
  2065. *
  2066.  
  2067. ;                                             _
  2068. BLITLF        set    ABC+ABNC+ANBNC+NABC        Results into: D=AC+BC
  2069. BLITUSE        set    SRCA+SRCB+DEST            Two sources and one destination
  2070. SHIFTA        set    1<<ASHIFTSHIFT            Shift source A by one bit
  2071. SHIFTB        set    0<<BSHIFTSHIFT
  2072.  
  2073. CTL0        set    SHIFTA+BLITUSE+BLITLF
  2074. CTL1        set    SHIFTB+BC1F_DESC        Descending: shift right, Area mode
  2075.  
  2076. BF_DS10        bsr.s    BF_SetBlitMod
  2077.         move.l    TSBN_P0(a1),bltapt(a0)        Source pointer A
  2078.         move.l    TSBN_P1(a1),bltbpt(a0)        Source pointer B
  2079.         move.l    TSBN_P2(a1),bltdpt(a0)        Destination
  2080.         move.w    #$5555,bltcdat(a0)        Datamask into C data register
  2081.         move.l    #CTL0<<16+CTL1,bltcon0(a0)    Instruct blitter its operation
  2082.         move.w    #((TD_SECTOR/2)<<HSIZEBITS)+1,bltsize(a0)    Start blit
  2083.         bra.s    BF_QuitBlit
  2084.  
  2085.  
  2086.  
  2087. *-------------------------------------------------------*
  2088. *
  2089. *  Shift and move a block from one place to another
  2090. *
  2091.  
  2092. BLITLF        set    ABC+ABNC+NABC+NABNC        D=B
  2093. BLITUSE        set    SRCB+DEST            B is source and D destination
  2094. SHIFTA        set    0<<ASHIFTSHIFT            Shift source A by one bit
  2095.  
  2096. CTL0        set    SHIFTA+BLITUSE+BLITLF
  2097.  
  2098. BF_BM10        bsr.s    BF_SetBlitMod
  2099.         move.w    #CTL0,bltcon0(a0)
  2100.         move.w    TSBN_C1(a1),bltcon1(a0)        Shift factor into BSH (B-shift) ascending
  2101.         move.l    TSBN_P1(a1),bltbpt(a0)        Source into B
  2102.         move.l    TSBN_P2(a1),bltdpt(a0)        Destination into D
  2103.         move.w    bn_blitsize(a1),bltsize(a0)    Start blit by writing size
  2104.         bra.s    BF_QuitBlit
  2105.  
  2106. *-------------------------------------------------------*
  2107. *
  2108. *  Compare two blocks (1)
  2109. *
  2110. *  We perform a XOR on both blocks.  The result must always be zero.  We do not
  2111. *  store the result.  Therefore we use source C, which limits the operation to
  2112. *  four ticks.  The next function checks the bltnzero bit in the dmaconr register.
  2113. *  
  2114.  
  2115. ;                               _ _
  2116. BLITLF        set    ABNC+NABC            D=AC+AC
  2117. BLITUSE        set    SRCA+SRCC
  2118. SHIFTA        set    0<<ASHIFTSHIFT
  2119. SHIFTB        set    0<<BSHIFTSHIFT
  2120.  
  2121. CTL0        set    SHIFTA+BLITUSE+BLITLF
  2122. CTL1        set    SHIFTB                Ascending, Area
  2123.  
  2124. BF_CMP10    bsr    BF_SetBlitMod
  2125.         move.l    #CTL0<<16+CTL1,bltcon0(a0)    Instruct blitter its operation
  2126.         move.w    #$FFFF,bltbdat(a0)        Validate AND operation
  2127.  
  2128.         move.l    TSBN_P0(a1),bltapt(a0)        Original trackbuffer into A
  2129.         move.l    TSBN_P1(a1),bltcpt(a0)        Begin of same sector in verify buffer into C
  2130.         move.w    bn_blitsize(a1),d0        Number of sectors of first block to compare
  2131.         beq.s    BF_CMP202            Is zero, we go directly to the second compare
  2132.         or.w    #((SE_SIZE/2)<<HSIZEBITS),d0    Merge sector size into blitsize word
  2133.         move.w    d0,bltsize(a0)            Start blit
  2134.  
  2135.         lea.l    BF_CMP20(pc),a0
  2136.         move.l    a0,bn_function(a1)        Next function    
  2137.         ;moveq    #-1,d0            
  2138.         rts
  2139.  
  2140. *-------------------------------------------------------*
  2141. *
  2142. *  Compare two blocks (2)
  2143. *
  2144. *  The second compare starts with a check of the first compare.  Then the second
  2145. *  compare is passed to the bitter.
  2146. *
  2147.  
  2148. BF_CMP20    bsr.s    BF_TestZero            Test result of last compare
  2149.         bmi.s    BF_End                Error, no need to continue..
  2150.  
  2151. BF_CMP202    moveq.l    #SPT,d0                Total number of sectors
  2152.         sub.w    bn_blitsize(a1),d0        Subtract number of sectors already compared
  2153.         beq    BF_End                All compared..
  2154.         or.w    #((SE_SIZE/2)<<HSIZEBITS),d0    Merge sector size into blitsize word
  2155.         move.l    TSBN_P2(a1),bltcpt(a0)        Pointer to second block into C
  2156.         move.w    d0,bltsize(a0)            Start blit
  2157.         lea.l    BF_CMP30(pc),a0
  2158.         move.l    a0,bn_function(a1)        Next function    
  2159.         moveq    #-1,d0            
  2160.         rts
  2161.  
  2162. *-------------------------------------------------------*
  2163. *
  2164. *  End Compare
  2165. *
  2166. *  Check the result of the second compare and quit
  2167. *
  2168.  
  2169. BF_CMP30    bsr.s    BF_TestZero            Set return value of this compare
  2170.         bra.s    BF_End                Continue QBlit end function
  2171.         
  2172. BF_TestZero    move.w    dmaconr(a0),d0            Dma status word
  2173.         btst    #DMAB_BLTNZERO,d0        Did blitter had once or more a non-zero result?
  2174.         bne.s    10$                No..
  2175.         moveq.l    #-1,d0                Yes, -1 means error
  2176.         move.l    d0,TSBN_P3(a1)            Set return value
  2177. 10$        rts        
  2178.  
  2179. *-------------------------------------------------------*
  2180. *
  2181. *  QBlit end function
  2182. *
  2183. *  Inform task all blitter operations are done and terminate.
  2184. *
  2185.  
  2186. BF_End        move.l    TSBN_Unit(a1),a1        TD unit pointer
  2187.         bsr    TD_Reply            A6F2
  2188.         moveq.l #0,d0                Return 0 to stop QBlit
  2189.         rts
  2190.  
  2191.  
  2192. *********************************************************
  2193. *
  2194. *  End of code to be copied to the allocated space.  Would this be the allocted space,
  2195. *  then the TD-copy would begin here.
  2196. *  From here it is allowed again to make the location counter external available.
  2197. *
  2198.  
  2199. TSCodeEnd
  2200. TD
  2201.  
  2202. TD_NoDisk    equ    TD+$00DE    99C2
  2203. TD_ChkDiskPres    equ    TD+$00FC    99E0
  2204. TD_IOReply    equ    TD+$08CC    A1B0
  2205. TD_Seek        equ    TD+$0AF6    A3DA
  2206. TD_SwitchMotor    equ    TD+$0B7E    A462
  2207. TD_Sleep    equ    TD+$0C0C    A4F0
  2208. TD_ReadDisk    equ    TD+$0C40    A524
  2209. TD_Reply    equ    TD+$0E0E    A6F2
  2210. TD_WaitTDPort    equ    TD+$0E26    A70A
  2211. TD_CmdCheck    equ    TD+$0F20    A804
  2212. TD_CmdWrite    equ    TD+$0F34    A818
  2213. TD_CmdRead    equ    TD+$0FAC    A890
  2214. TD_CmdRead10    equ    TD+$0FBC    A8A0
  2215. TD_EndRW    equ    TD+$103C    A920
  2216. TD_WriteTrack    equ    TD+$1074    A958
  2217. TD_440b        equ    TD+$109E    A982
  2218. TD_ReadTrkRetry equ    TD+$1106    A9EA
  2219. TD_ReadTrkRtn    equ    TD+$1114    A9F8
  2220. TD_CorrectEdge    equ    TD+$14DA    ADBE
  2221. TD_TaskLoop    equ    TD+$1580    AE64
  2222. TD_NormTrack    equ    TD+$16FE    AFE2
  2223. TD_NormTrackRtn equ    TD+$18F0    B1D4
  2224. TD_BadSecID    equ    TD+$1910    B1F4
  2225. TD_BadHdrSum    equ    TD+$1914    B1F8
  2226.  
  2227.  
  2228. *********************************************************
  2229. *
  2230. *  This table contains data which will be put into the trackdisk code we copied from ROM.
  2231. *  Its location must directly follow TSCodeEnd for offset calculations.  So do not reposition
  2232. *  this table without an adaption of the Patch macro.
  2233. *  The format of a table entry has following form:
  2234. *
  2235. *  WORD        OffsetInTD        Offset relative to rt_MatchTag
  2236. *  UWORD    PatchSize        Size of patch in words
  2237. *  STRUCT    Patch,PatchSize*2    The patch itself
  2238. *
  2239. *  The Patch table consists of a series of patch structures following each other.  The end
  2240. *  of the table is reached when a patch is met with a PatchSize of zero.
  2241. *
  2242.  
  2243. Patch        MACRO    <Offset in TD>,<Patchsize in bytes>
  2244.         dc.w    \1
  2245.         dc.w    (\2)/2
  2246. TS        set    *-TD-\1
  2247.         ENDM
  2248.  
  2249.         Func    TSPatchTable,_TSPatchTable
  2250.  
  2251. *--    Bug patches
  2252.  
  2253.         Patch    $1A38,P000e-P000b        B31C Bug in td_RawWrite
  2254. P000b        cmp.l    #$7fff,d0            Now immediate instead of absolute indirect
  2255. P000e
  2256.         Patch    $00E4,P001e-P001b        99C8 Disk presence check AAAAAAAAARRRRRRRGGGHHHH...
  2257. P001b        bne.w    TS+TD_ChkDiskPres        99E0 GetUnit before hardware access patch
  2258. P001e
  2259.         Patch    $1A24,P002e-P002b        B308 Bug in td_RawWrite
  2260. P002b        cmp.w    TDU_NTracks(a3),d0        Now compare word-size instead of long
  2261. P002e
  2262.         Patch    $07FC,P003e-P003b        A0E0 Bug in td_Format
  2263. P003b        cmp.w    TDU_NTracks(a3),d0        Now compare word-size instead of long
  2264. P003e
  2265.  
  2266. *--    Let toplevel task loop flow through our code
  2267.  
  2268.         Patch    $1592,P100e-P100b        AE76 Toplevel task loop
  2269. P100b        bra.w    TS+TDE_TaskLoop            Extent taskloop
  2270. P100e
  2271.  
  2272. *--    Check first with us before clicking
  2273.  
  2274.         Patch    $0104,P200e-P200b        99E8 Presence test
  2275. P200b        bsr.w    TS+TDE_NoClick            Check function active before clicking
  2276.         nop
  2277. P200e
  2278.  
  2279. *--    Check readonly simutation before writes or returning td_ProtStatus
  2280.  
  2281.         Patch    $0D22,P300e-P300b        A606 Write routine
  2282. P300b        bsr.w    TS+TDE_WriteProt        Check first our protect bit
  2283.         nop
  2284.         nop
  2285. P300e
  2286.         Patch    $1194,P301e-P301b        AA78 Tab-test for td_ProtStatus
  2287. P301b        bsr.w    TS+TDE_WriteProt1        Check first our protect bit
  2288. P301e
  2289.  
  2290. *--    Read/write adaptions to the salve function and type of memory of the IO buffers
  2291.  
  2292.         Patch    $0E50,P400e-P400b        A734 
  2293. P400b        movem.l    d2/d6/a2-a4,-(a7)        We use d2 as error flag for IO of salved tracks and d6 as memtype
  2294. P400e
  2295.         Patch    $0E5E,P405e-P405b        A742 Clear IO_ACTUAL
  2296. P405b        bsr.w    TS+TDE_CMD_RW            Set d2 to zero, memtype of IO buffers, Write to Prot. disk?
  2297.         bne.w    TS+TD_EndRW
  2298. P405e
  2299.         Patch    $0ECA,P410e-P410b        A7AE Get trackbuffer
  2300. P410b        move.l    TDU_UnitBuf(a3),a0
  2301. P410e
  2302.         Patch    $0F0E,P415e-P415b        A7F2 Error in trackbuffer
  2303. P415b        move.l    TDU_IOReq(a3),a1
  2304.         bsr    TS+TDE_CheckBuf            Test read or write or salved
  2305.         bne.s    TS+TD_CmdCheck            Read salved track..
  2306.         bra.w    TS+TD_EndRW            A920 We do not write or track not salved, leave..
  2307. P415e
  2308.         Patch    $0F30,P420e-P420b        A814 Branch read or write
  2309. P420b        bne.w    TS+TDE_ReadCheck        Read, but perhaps the track is salved, special care..
  2310. P420e
  2311.         Patch    $1040,P425e-P425b        A924 Calling Reply IORequest
  2312. P425b        bsr.w    TS+TDE_ChkActual        Check first for updating IO_ACTUAL and the write update counter
  2313. P425e
  2314.         Patch    $1052,P430e-P430b        A936
  2315. P430b        movem.l    (a7)+,d2/d6/a2-a4        Restore d2 and d6
  2316. P430e
  2317.         Patch    $1058,P435e-P435b        A73C Return buffer if buffer contains track d0
  2318. P435b        move.l    TDU_UnitBuf(a3),a0        Get trackdisks own buffer
  2319.         ;cmp.w    TB_TrkNo(a0),d0            Requested track in buffer?
  2320.         cmp.w    (a0),d0                Requested track in buffer?
  2321.         bne.s    10$                No..
  2322.         cmp.b    #CMD_WRITE,IO_COMMAND+1(a2)    Are we writing?
  2323.         bne.s    20$                No, return buffer..
  2324.         cmp.b    #SPT,TB_FirstSec(a0)        Salved track?
  2325.         bcs.s    20$                No, return buffer..
  2326. 10$        sub.l    a0,a0                Return null
  2327. 20$        rts
  2328. P435e
  2329.         ifgt    P435e-P435b-28
  2330.         FAIL    Patch too long, will not fit!
  2331.         endc
  2332.         
  2333.         Patch    $109E,P440e-P440b        A982 Unused area in trackdisk
  2334. P440b        btst.b    #B_SALVE,UNIT_pad(a3)        TD stops, are we going to do something about it?
  2335.         beq.s    TS+TD_ReadTrkRtn        A9F8 No, function not active, continue TD..
  2336.         move.l    TDU_IOReq(a3),a0
  2337.         cmp.b    #CMD_WRITE,IO_COMMAND+1(a0)    Are we reading for preparing a write?
  2338.         beq.s    TS+TD_ReadTrkRtn        A9F8 Yes, writes are not allowed on salved tracks, continue TD..
  2339.         bsr    TS+RepairTrack            No, it is a read, we give it a try..
  2340.         bra.s    TS+TD_ReadTrkRtn        A9F8 Continue TD..
  2341. P440e        
  2342.         ifgt    P440e-P440b-28
  2343.         FAIL    Patch too long, will not fit!
  2344.         endc
  2345.  
  2346.         Patch    $1104,P445e-P445b        A9E8 Read error after normalisation
  2347. P445b        bgt.s    TS+TD_440b            A982 Check first with us before giving up
  2348. P445e
  2349.  
  2350. *--    Change some errors which are meaningless outside Trackdisk
  2351.  
  2352.         Patch    $1796,P450e-P450b        B07A Search for a sector in Normalize
  2353. P450b        bne.w    TS+TD_BadHdrSum            Was: BadSecHdr
  2354. P450e
  2355.         Patch    $17AC,P451e-P451b        B090 Search for a sector in Normalize
  2356. P451b        bne.w    TS+TD_BadSecID            Was: BadSecHdr
  2357. P451e
  2358.         Patch    $17B8,P452e-P452b        B09C Search for a sector in Normalize
  2359. P452b        bne.w    TS+TD_BadSecID            Was: BadSecHdr
  2360. P452e
  2361.  
  2362. *--    Verify adaptions to write routines
  2363.  
  2364.         Patch    $07C4,P500e-P500b        A0A8 Write updated track to disk in format routine
  2365. P500b        bsr    TS+TDR_WriteTrack
  2366. P500e
  2367.         Patch    $0EDC,P502e-P502b        A7C0 Write updated track to disk in device i/o (before seek)
  2368. P502b        bsr    TS+TDR_WriteTrack
  2369. P502e
  2370.         Patch    $11D6,P503e-P503b        AABA Write updated track to disk in CMD_UPDATE
  2371. P503b        bsr    TS+TDR_WriteTrack
  2372. P503e
  2373.         Patch    $15D2,P504e-P504b        AEB6 Write updated track to disk in close device
  2374. P504b        bsr    TS+TDR_WriteTrack
  2375. P504e
  2376.  
  2377. *--    Verify adaptions to the "raw track to writable track" convert routine
  2378.  
  2379.         Patch    $16FE,P520e-P520b        AFE2 Begin of this routine
  2380. P520b        movem.l d0/d2-d6/a2,-(a7)        D0 added to list, has become an argument now available on stack
  2381. P520e
  2382.         Patch    $180A,P521e-P521b        B0EE Replacement of calling CorrectEdge, which is obsolete
  2383. P521b        tst.l    20(a7)                TD calls this routine with zero saved here
  2384.         bne.w    TS+TD_NormTrackRtn        B1D4 Called by the verify routine, skip header revision..
  2385. P521e
  2386.         Patch    $18FA,P522e-P522b        B1DE End of this routine
  2387. P522b        movem.l (a7)+,d1/d2-d6/a2        D1 added to list as a dummy pull to compensate above
  2388. P522e
  2389.  
  2390. *--    Verify adaption to Format routine
  2391.  
  2392.         Patch    $0864,P541e-P541b        A148  Bring format routine to follow standard write path
  2393. P541b        move.w    d2,TB_TrkNo(a0)            Set tracknumber in trackbuffer
  2394.         move.l    a0,TDU_DiskBuf(a3)        Trackdisk's buffer is write buffer
  2395.         bsr.w    TS+TDR_WriteTrackF        Call (almost) standard write routine
  2396. P541e
  2397.  
  2398. *--    New coding routines
  2399.  
  2400.         Patch    $1462,P600e-P600b        AD46 Encode a longword routine
  2401. P600b        move.l    d0,d1                Encode one longword
  2402.         lsr.l    #1,d0                Even bits
  2403.         move.l    d0,(a0)+            Store even bits
  2404.         move.l    d1,(a0)+            Store odd bits
  2405.         rts                    ; We do not care about the timing bits
  2406. P600e
  2407.         Patch    $0F6A,P601e-P601b        A84E Device write routine, label flag was set
  2408. P601b        bsr.w    TS+TDR_EncodeLabel        Encode it simple and with the CPU
  2409. P601e
  2410.         Patch    $0F90,P602e-P602b        A874 Device write routine, write sector
  2411. P602b        bsr.w    TS+TDR_EncodeSect        Replace encoding by our routines
  2412. P602e
  2413.         Patch    $1248,P603e-P603b        AB2C Build a complete sector for TD_FORMAT
  2414. P603b        bsr.w    TS+TDR_EncodeSect        Replace encoding by our routines
  2415. P603e
  2416.  
  2417.         Patch    $0FDC,P650e-P650b        A8C0 Device read routine, read label
  2418. P650b        bsr.w    TS+TDR_DecodeLabel        Replace decoding by our routines
  2419. P650e
  2420.         Patch    $0FEE,P651e-P651b        A8D2 Device read routine, read sector
  2421. P651b        bsr.w    TS+TDR_DecodeSect        Replace decoding by our routines
  2422. P651e
  2423. *        Patch    $13C2,P652e-P652b        ACA6 -- not used by Trackdisk
  2424. *P652b        bsr.w    TS+TDR_DecodeSect        Replace decoding by our routines
  2425. *P652e
  2426.  
  2427. *--    Type of memory in format routine
  2428.  
  2429.         Patch    $0796,P670e-P670b        A07A Begin of format routine
  2430. P670b        movem.l    d2-d6/a2/a5,-(a7)        D6 added to list as flag for type of mem
  2431. P670e
  2432.         Patch    $0804,P672e-P672b        A0E8 Just before encoding loop in format routine
  2433. P672b        bsr.w    TS+TDE_FormInit            Find out what kind of memory is used for IO
  2434. P672e
  2435.         Patch    $0890,P674e-P674b        A174 End of format routine
  2436. P674b        movem.l    (a7)+,d2-d6/a2/a5        D6 added to list
  2437. P674e
  2438.  
  2439. *--    Update routines
  2440.  
  2441.         Patch    $0BD6,P700e-P700b        A4BA  Continuation of motor switch
  2442. P700b        bra.w    TS+TDE_SetUpdCnt        Set or clear the counter
  2443. P700e
  2444.  
  2445. *  Setting the counter after a change of the trackbuffer (CMD_WRITE) is done in the Read/Write patches (P4..)
  2446.  
  2447.         Patch    $00A4,P702e-P702b        9988  Continuation of disk presence check
  2448. P702b        bra.w    TS+TDE_CheckUpdate        Decrement counter and switch the motor off if elapsed
  2449. P702e
  2450.  
  2451.         
  2452. *--    List termination
  2453.  
  2454.         Patch    0,0
  2455.  
  2456.  
  2457. *********************************************************
  2458. *
  2459. *  The relocation table of the code between TSCodeBegin and TSCodeEnd.
  2460. *
  2461.  
  2462.         Func    TSCodeRelocTable
  2463.  
  2464.         dc.w    NEW_ReqGadget-TSCodeBegin
  2465.         dc.w    NEW_ReqTitle-TSCodeBegin
  2466.         dc.w    IMG_ReqNext-TSCodeBegin
  2467.         dc.w    GAD_Positive-TSCodeBegin
  2468.         dc.w    GAD_PosRender-TSCodeBegin
  2469.         dc.w    GAD_PosIText-TSCodeBegin
  2470.         dc.w    GAD_NegRender-TSCodeBegin
  2471.         dc.w    GAD_NegIText-TSCodeBegin
  2472.         dc.w    IT_B0Font-TSCodeBegin
  2473.         dc.w    IT_B0Text-TSCodeBegin
  2474.         dc.w    IT_B0Next-TSCodeBegin
  2475.         dc.w    IT_B1Font-TSCodeBegin
  2476.         dc.w    IT_B1Text-TSCodeBegin
  2477.         dc.w    IT_PosFont-TSCodeBegin
  2478.         dc.w    IT_PosText-TSCodeBegin
  2479.         dc.w    IT_PosNext-TSCodeBegin
  2480.         dc.w    IT_NegFont-TSCodeBegin
  2481.         dc.w    IT_NegText-TSCodeBegin
  2482.         dc.w    TA_Topaz8-TSCodeBegin
  2483.         dc.w    0
  2484.  
  2485.  
  2486. *********************************************************
  2487. *
  2488. *  The size of the code to be copied is EndTSCode-_TSCode.  The size of the buffer is
  2489. *  also assembler laid down.
  2490. *  How do we pass these values to a C-module?
  2491. *  For now with globals, but constants would be more appropriate..
  2492. *
  2493.  
  2494.         SECTION __MERGED,data
  2495.  
  2496.         gc_l    _TSCodeSize,TSCodeEnd-TSCodeBegin
  2497.         gc_l    _BufferSize,SB_SIZE
  2498.         gc_l    _PCSubOffset,FirstPCSub-TSCodeBegin
  2499.         gc_l    _PCWaitOffset,FirstPCWait-TSCodeBegin
  2500.  
  2501. *********************************************************
  2502.  
  2503.         END
  2504.  
  2505.